| 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