您的位置:首页 > 其它

poj-3254 Corn Fields 状态压缩dp

2016-01-27 08:35 363 查看
题意:一农民有一片N*M的地,地里的土地有的肥沃有的不肥沃,0表示不肥沃,1相反。农民需要往这片地里放养牛,一只牛只能在一块1*1的地里且只在肥沃的地里。牛的数量不限,问这片地里能有多少种放牛的情况。

思路:首先能确定这是一道dp题,为了简化dp的状态存储,使用了状态压缩,我们可以用一个二进制数来表示一行中土地是否肥沃的情况或者表示一行里能放牛的所有情况,题中说明一行最多12个地那么我们用一个12位的二进制数就可以表示土地和放牛的情况了,例如1表示有牛0是没有。首先我们在输入的时候将n*m的土地情况转化成n个数来表示n行,然后找出对于一行m列所有的放牛情况k个。之后初始化dp数组第一行,将所有的放牛情况与土地情况匹配,如果符合题意那么dp[1][j]=1。其中j就表示了这行土地中的一种放牛情况。之后的所有行中,我们除了与土地情况匹配,还需要与上一层放牛的情况核对,看看是否有冲突。

#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#define INF 0x3f3f3f3f
#define mod 100000000
using namespace std;

int main()
{
int mp[30];
long long dp[20][5000];
int poss[6000];
int n,m,x;
int k=0;
memset(poss,0,sizeof(poss));
memset(mp,0,sizeof(mp));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&x);
if(x==0)                        //为了方便土地与放牛的核对,我们将不肥沃的土地标为1
mp[i] += 1;
if(j!=m) mp[i]<<=1;
}
}
for(int i=0;i<(1<<m);i++)               //对于一行m块地找出所有放牛的情况
{
if(!(i&(i<<1)))
poss[k++]=i;
}
for(int i=0;i<k;i++)                    //初始化第一行dp数组
{
if(!(poss[i]&mp[1]))
{
dp[1][i]=1;
dp[1][k] ++;
}
}
int sum;
for(int i=2;i<=n;i++)
{
for(int j=0;j<k;j++)                    //判断j放牛情况是否符合第i行土地
{
if(!(poss[j]&mp[i]))
{
sum=0;
for(int l=0;l<k;l++)            //统计与上一行冲突的数量
{
if(dp[i-1][l]!=0&&(poss[l]&poss[j]))
{
sum+=dp[i-1][l];
}
}
dp[i][j] = dp[i-1][k]-sum;
dp[i][k] = (dp[i][k]+dp[i][j])%mod;
}
}
}
printf("%lld\n",dp
[k]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: