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;
}

  

posted @ 2020-09-18 15:34  coastal_taipan  阅读(107)  评论(0)    收藏  举报