POJ2441 Arrange the Bulls(状压DP)

题目是,有n头牛,每头牛都喜爱某几个草地,要把这n头牛分配给m个不同的它们喜爱的草地,问有几种分配方式。

  • dp[n][S]表示前n头牛分配完毕后占用的草地集合是S的方案数
  • dp[0][0]=1
  • dp[n][S]+=dp[n-1][S-x](x∈S且n喜爱x)

不过的状态这样空间开销太大了,事实上n这个维度的信息S就包含了,所以dp[S]即可。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 int d[1<<20];
 6 bool map[22][22];
 7 int main(){
 8     int n,m,p,a;
 9     scanf("%d%d",&n,&m);
10     for(int i=0; i<n; ++i){
11         scanf("%d",&p);
12         while(p--){
13             scanf("%d",&a);
14             map[i][a-1]=1;
15         }
16     }
17     int res=0;
18     d[0]=1;
19     for(int i=1; i<(1<<m); ++i){
20         int cnt=-1;
21         for(int j=0; j<m; ++j){
22             if((i>>j)&1) ++cnt;
23         }
24         for(int j=0; j<m; ++j){
25             if(((i>>j)&1) && map[cnt][j]) d[i]+=d[i^(1<<j)];
26         }
27         if(cnt==n-1) res+=d[i];
28     }
29     printf("%d",res);
30     return 0;
31 }

 

转载于:https://www.cnblogs.com/WABoss/p/5188668.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值