题意:有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;
}
思路:状态压缩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
#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 ()
{
}