POJ 2441 Arrange the Bulls(状态压缩DP)

时间:2023-03-08 22:38:57
POJ 2441 Arrange the Bulls(状态压缩DP)

题意很简单,n头牛,m个位置,每头牛有各自喜欢的位置,问安排这n头牛使得每头牛都在各自喜欢的位置有几种安排方法。

2000MS代码:

#include <cstdio>
#include <cstring>
int dp[(<<)+];
int one[( << ) + ];
//用来数出状态为i时1的个数,具体到这个题中就是
//状态为i时有多少头牛已经安排好牛棚
void CountOne(int m)
{
for(int i=; i< ( << m); ++i)
{
int num=;
for(int j=; j< m; ++j)
{
if( (i & ( << j)) != )//i的第j位置是否为一
++num;
}
one[i] = num;
}
}
int main()
{
// freopen("in.cpp","r",stdin);
int n,m;
scanf("%d%d",&n,&m);
CountOne(m);
memset(dp,,sizeof(dp));
dp[] = ; //一头牛都没有安排,状态为0的满足条件的方案数为1
for(int i=; i<=n; ++i)
{
int cnt; //每头牛喜欢住的牛棚数
scanf("%d",&cnt);
while(cnt--)
{
int k; //该牛棚编号
scanf("%d",&k);
--k;//使得牛棚编号为 0 ~ m-1
for(int j=; j< ( << m); ++j)
{
if((j & ( << k)) != && one[j] == i) //这个状态已经安排好了i头牛,且第k个牛棚安排的是第i头牛
dp[j] += dp[j-(<<k)];
}
}
}
// 最终结果为安排了n头牛的状态满足条件的方案数的总和
int ans=;
for(int j=; j< ( << m ); ++j)
{
if(one[j] == n)
{
ans += dp[j];
}
}
printf("%d\n",ans);
return ;
}

90MS

#include <stdio.h>
#include <string.h> int map[][];
int now[(<<)+]; int main()
{
int i,j,n,m,k,x,p,ret;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(map,,sizeof(map));
for (i=;i<n;i++)
{
scanf("%d",&k);
while(k--)
{
scanf("%d",&x);
x--;//0~m-1编号
map[i+][x]=;
}
}
if (n>m)
{
printf("0\n");
continue;
}
memset(now,,sizeof(now));
now[]=;
for (i=;i<n;i++)
{
for (j=(<<m)-;j>=;j--)
{
if (now[j]==) continue;
for (k=;k<m;k++)
{
if ((j & (<<k))!=) continue;//判断j的第k的位置为1
if (map[i+][k]==) continue;//在k的棚没有位置
p=(j | (<<k));//j的第k的位置变1
now[p]+=now[j];
}
now[j]=;
}
}
ret=;
for (i=;i<(<<m);i++)
{
ret+=now[i];
}
printf("%d\n",ret);
}
return ;
}