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 }

猜你喜欢

转载自www.cnblogs.com/ibilllee/p/9313924.html
今日推荐