POJ 2441 Arrange the Bulls(状态压缩DP)
题意很简单,n头牛,m个位置,每头牛有各自喜欢的位置,问安排这n头牛使得每头牛都在各自喜欢的位置有几种安排方法。
2000MS代码:
#include <cstdio> #include <cstring> int dp[(1<<20)+2]; int one[(1 << 20) + 2]; //用来数出状态为i时1的个数,具体到这个题中就是 //状态为i时有多少头牛已经安排好牛棚 void CountOne(int m) { for(int i=0; i< (1 << m); ++i) { int num=0; for(int j=0; j< m; ++j) { if( (i & (1 << j)) != 0)//i的第j位置是否为一 ++num; } one[i] = num; } } int main() { // freopen("in.cpp","r",stdin); int n,m; scanf("%d%d",&n,&m); CountOne(m); memset(dp,0,sizeof(dp)); dp[0] = 1; //一头牛都没有安排,状态为0的满足条件的方案数为1 for(int i=1; i<=n; ++i) { int cnt; //每头牛喜欢住的牛棚数 scanf("%d",&cnt); while(cnt--) { int k; //该牛棚编号 scanf("%d",&k); --k;//使得牛棚编号为 0 ~ m-1 for(int j=0; j< (1 << m); ++j) { if((j & (1 << k)) != 0 && one[j] == i) //这个状态已经安排好了i头牛,且第k个牛棚安排的是第i头牛 dp[j] += dp[j-(1<<k)]; } } } // 最终结果为安排了n头牛的状态满足条件的方案数的总和 int ans=0; for(int j=0; j< (1 << m ); ++j) { if(one[j] == n) { ans += dp[j]; } } printf("%d\n",ans); return 0; }
90MS
#include <stdio.h> #include <string.h> int map[25][25]; int now[(1<<20)+5]; int main() { int i,j,n,m,k,x,p,ret; while(scanf("%d%d",&n,&m)!=EOF) { memset(map,0,sizeof(map)); for (i=0;i<n;i++) { scanf("%d",&k); while(k--) { scanf("%d",&x); x--;//0~m-1编号 map[i+1][x]=1; } } if (n>m) { printf("0\n"); continue; } memset(now,0,sizeof(now)); now[0]=1; for (i=0;i<n;i++) { for (j=(1<<m)-1;j>=0;j--) { if (now[j]==0) continue; for (k=0;k<m;k++) { if ((j & (1<<k))!=0) continue;//判断j的第k的位置为1 if (map[i+1][k]==0) continue;//在k的棚没有位置 p=(j | (1<<k));//j的第k的位置变1 now[p]+=now[j]; } now[j]=0; } } ret=0; for (i=0;i<(1<<m);i++) { ret+=now[i]; } printf("%d\n",ret); } return 0; }