Time Limit: 4000MS | Memory Limit: 65536K | |
Total Submissions: 3509 | Accepted: 1344 |
Description
Input
Output
Sample Input
3 4 2 1 4 2 1 3 2 2 4
Sample Output
4
刚开始学习状压DP,有理解不对的还忘指正,谢谢。
参考的代码:http://blog.csdn.net/magicnumber/article/details/6647980
参考资料:http://www.hankcs.com/program/algorithm/poj-2441-arrange-the-bulls.html
我对代码的理解
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int map[25][25]; int dp[(1<<20)+100]; int main() { int n,m; while(~scanf("%d%d",&n,&m)) { int p; memset(map,0,sizeof(map)); for(int i=1;i<=n;i++) { scanf("%d",&p); for(int j=1;j<=p;j++) { int x; scanf("%d",&x); x--;//1移x-1位就是第x个1 map[i][x]=1; } } if(n>m) { printf("0\n"); continue; } memset(dp,0,sizeof(dp)); dp[0]=1;//全部都不选 for(int i=1;i<=n;i++) { for(int j=(1<<m)-1;j>=0;j--)//枚举子集 { if(!dp[j])//如果该子集不存在,跳过 continue; for(int k=0;k<m;k++)//向子集中添加元素 { if(((1<<k)&j)!=0)//该元素已经在子集中了就跳过 continue; if(map[i][k]==0)//不能取该元素 continue; int temp=((1<<k)|j);//添加元素后的新的值 dp[temp]+=dp[j];//添加元素 } dp[j]=0;//这个子集就不存在了。 } } long long ans=0; for(int i=0;i<(1<<m);i++) ans+=dp[i]; printf("%I64d\n",ans); } return 0; }
poj 2441 Arrange the Bulls(状压DP入门)
原文:http://blog.csdn.net/caduca/article/details/40299279