Arrange the Bulls [POJ2441] [状压DP]
Posted ibilllee
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Arrange the Bulls [POJ2441] [状压DP]相关的知识,希望对你有一定的参考价值。
题意
n头牛,m个房间,每头牛有自己喜欢的房间,问每头牛都住进自己喜欢的房间有多少种分配方法?
Input
In the first line of input contains two integers N and M (1 <= N <= 20, 1 <= M <= 20). Then come N lines. The i-th line first contains an integer P (1 <= P <= M) referring to the number of barns cow i likes to play in. Then follow P integers, which give the number of there P barns.
Output
Print a single integer in a line, which is the number of solutions.
Sample Input
3 4
2 1 4
2 1 3
2 2 4
Sample Output
4
Analysis
首先,这种数据我们很容易想到是状压DP
我们可以比较轻松的写出状态转移方程
if(status&(1<<room)==0)
dp[i][status|(1<<room)]+=dp[i-1][status];
但是我们发现这样是会MLE的,我们就可以采用滚动数组,或是直接上一维
一维要注意status从大到小循环,因为是每次小的更新大的,status用完之后要清零。
Code
1 #include<set> 2 #include<map> 3 #include<queue> 4 #include<stack> 5 #include<cmath> 6 #include<cstdio> 7 #include<cstring> 8 #include<iostream> 9 #include<algorithm> 10 #define RG register int 11 #define rep(i,a,b) for(RG i=a;i<=b;++i) 12 #define per(i,a,b) for(RG i=a;i>=b;--i) 13 #define ll long long 14 #define inf (1<<29) 15 using namespace std; 16 int n,m,ans; 17 int a[25][25]; 18 int dp[1048600]; 19 inline int read() 20 { 21 int x=0,f=1;char c=getchar(); 22 while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} 23 while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} 24 return x*f; 25 } 26 27 28 int main() 29 { 30 n=read(),m=read(); 31 rep(i,1,n) 32 { 33 a[i][0]=read(); 34 rep(j,1,a[i][0]) 35 a[i][j]=read(); 36 } 37 dp[0]=1; 38 rep(i,1,n) 39 { 40 per(j,(1<<m)-1,0) 41 { 42 if(!dp[j]) continue; 43 rep(k,1,a[i][0]) 44 { 45 if(!(j&(1<<(a[i][k]-1)))) 46 { 47 dp[j|(1<<(a[i][k]-1))]+=dp[j]; 48 } 49 } 50 dp[j]=0; 51 } 52 } 53 int ans=0; 54 per(j,(1<<m)-1,0) ans+=dp[j]; 55 cout<<ans; 56 return 0; 57 }
以上是关于Arrange the Bulls [POJ2441] [状压DP]的主要内容,如果未能解决你的问题,请参考以下文章
POJ2441 Arrange the Bulls(状压DP)
LightOJ - 1095 - Arrange the Numbers(错排)
Light oj 1095 - Arrange the Numbers (组合数学+递推)