poj2441 Arrange the Bulls
题目链接: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;
}

浙公网安备 33010602011771号