题目链接:https://vjudge.net/problem/POJ-2441
题意:n头牛,每头牛都有自己喜欢的几个barn,要把所有的牛都安排进自己喜欢的barn且没有两个在同一个barn,求方案数
设二进制状态为1表示放了牛,为0表示没有放,f[i][s]表示放了前i头牛,此时状态为s的方案数,则有:
f[i][s]=Σf[i-1][s'],s'=s^(1<<j),如果牛i能放在第j个barn,且第j个barn有牛
一开始纠结怎么去掉不合法的状态避免多余计算,其实合法的状态只有放完i头牛后,二进制表示下1的个数为i的状态,这个可以用__builtin_popcount判断。另外本题需要用滚动数组
#include<iostream> using namespace std; int a[25][25],f[2][(1<<22)],n,m,p,s,i,j,k; int main(){ cin>>n>>m; for (i=1;i<=n;i++){ cin>>p; int x; for (j=1;j<=p;j++) { cin>>x; a[i][x-1]=1; } } f[0][0]=1; for (i=1;i<=n;i++){ for (s=0;s<(1<<m);s++){ if (__builtin_popcount(s)!=i) continue; //* for (j=0;j<m;j++) if (s&(1<<j)&&a[i][j]) f[i&1][s]+=f[(i-1)&1][s^(1<<j)]; } for (s=0;s<(1<<m);s++) f[(i-1)&1][s]=0; //* } int ans=0; for (s=0;s<(1<<m);s++) ans+=f[n&1][s]; cout<<ans<<endl; return 0; }