poj 2441 Arrange the Bulls(状态…

题意:有N头牛,每头牛都有自己喜欢的barn 而且一个barn只能有一头牛,求给这些牛分配barn 共有多少种方法

思路:状态压缩DP,先说一下状态方程dp[i][j] 表示第i头牛在j的状态下的方法数 dp[i][j] = sigma(dp[i-1][k] ) k 从0 到 1<<(m-1); 这里用到滚到数组 因为dp[20][1<<20] 的数组会MLE。

//8384K      407MS
#include <stdio.h>
#include <string.h>
#define M 25

int dp[2][1<<20],a[M][M];//a[i][j] 为1 表示第i头牛能在第j列
int n,m;
int main ()
{
      int i,j,k,t,p;
      while (~scanf ("%d%d",&n,&m))
      {
              memset (a,0,sizeof(a));
              memset (dp,0,sizeof(dp));
              dp[0][0] = 1;
              for (i = 1; i <= n; i ++)
              {
                      scanf ("%d",&t);
                      while ( t --)
                      {
                              scanf ("%d",&p);
                              a[i][p] = 1;
                      }
              }
              for (i = 1; i <= n; i ++)
              {
                      for (j = 0; j < (1<<m); j ++)  //每种状态访问一次
                              if (dp[1-i&1][j])            //只有在前i-1头牛的j状态有值的情况下                                          才用确定在这种情况下第i头牛的放法
                              {
                                      for (k = 1; k <= m; k ++)
                                              if (a[i][k]&&(j!= (j|1<<(k-1))))//如果能放在k位置&&k位置没有其它的牛
                                                      dp[i&1][(j|1<<(k-1))] += dp[1-i&1][j];
                              }
                      memset (dp[1-i&1],0,sizeof(dp[1-i&1]));  //滚动数组
              }
      int ans = 0;
      for (i = 1;i < (1<<m);i ++)//统计结果
              ans += dp[n&1][i];
      printf ("%d\n",ans);
      }
      return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值