您的位置:首页 > 其它

POJ 3254 【状态压缩DP】

2015-11-06 19:30 288 查看
题意:

给一块n*m的田地,1代表肥沃,0代表贫瘠。

现在要求在肥沃的土地上种草,要求任何两个草都不能相邻。

问一共有多少种种草的方法。

种0棵草也是其中的一种方法。

n和m都不大于12.

思路:

状态压缩DP,dp[i][j]代表在第i行状态j一共有多少种可能的种植方法。

j是二进制转化而来的状态,0代表不种草,1代表种草。

dp[i]只受到两个限制,即dp[i-1]的某种状态,和当前土地的贫瘠状况。

只要保证&操作之后重复的为0就可以了

最后输出sum(dp
[1...w])(w代表一共有w种可行的状态)

#include<stdio.h>
int pho[15][15];
int biao[15];
int dp[15][1<<13];
int may[1<<13];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&pho[i][j]);
if(pho[i][j])
{
pho[i][j]=0;
}
else
{
pho[i][j]=1;
}
}
}
for(int i=1;i<=n;i++)
{
int tmp=pho[i][1];
for(int j=2;j<=m;j++)
{
tmp=tmp<<1;
tmp+=pho[i][j];
}
biao[i]=tmp;
}
int num=1;
for(int s=0;s<(1<<m);s++)
{
if((s&(s<<1))==0)
{
may[num++]=s;
}
}
for(int i=1;i<num;i++)
{
if((may[i]&biao[1])==0)
{
dp[1][i]=1;
}
}
for(int i=2;i<=n;i++)
{
for(int j=1;j<num;j++)
{
for(int k=1;k<num;k++)
{
if((may[k]&may[j])||(may[j]&biao[i]))
continue;
dp[i][j]+=dp[i-1][k];
dp[i][j]%=1000000000;
}
}
}
int ans=0;
for(int i=1;i<num;i++)
{
ans+=dp
[i];
ans%=1000000000;
}
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: