您的位置:首页 > 其它

pku 3254 Corn Fields 状态DP

2012-08-13 17:33 225 查看
http://poj.org/problem?id=3254

题意:

给定一个n*m的矩形,fj要在里面种玉米给奶牛吃,矩形内的小格中如果为1说明土地肥沃可以种植,如果为0说明土壤贫瘠不能种植玉米,而且奶牛们不喜欢在挨着的田地里吃玉米,问fj有多少种可选择方案种植玉米。

思路:

表示对状态dp不来感啊,首先dp[i][j]表示第i行在第j中状态下的可能数,则有dp[i][j] += dp[i - 1][k]这里k是在第i - 1行的所有状态中满足要求的状态。j也是在第i行满足要求的状态。

j,k满足要求的条件:1:满足当前行本身的种植条件;2:与上一行的种植情况要满足要求;

View Code

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <cmath>
#define CL(a,num) memset(a,num,sizeof(a))
#define M 13
#define N 13
#define MOD 100000000
using namespace std;

const int inf = 1999999;

int map
,dp
[1<<M];
int state[1<<M],ct;
int n,m,total;

bool isok(int x)
{
if (x&(x<<1)) return false;
else return true;
}
void init()
{
ct = 0;
int i;//将满足条件的行状态记录,(这里是左右不相邻)
for (i = 0; i < total; ++i)
{
if (isok(i)) state[ct++] = i;
}
}
int main()
{
//freopen("din.txt","r",stdin);
int a,i,j,k;
scanf("%d%d",&n,&m);
CL(map,0);
for (i = 0; i < n; ++i)
{
for (j = 0; j < m; ++j)
{
scanf("%d",&a);
if (a == 0) map[i] |= (1<<j);//记录每一行的本身的种植条件
}
}
total = (1<<m);
init();
CL(dp,0);
//初始化第一行
for (i = 0; i < ct; ++i)
{
if (!(map[0]&state[i]))
dp[0][state[i]]++;
}

for (i = 1; i < n; ++i)
{
for (j = 0; j < ct; ++j)
{
if (!(map[i]&state[j]))//首先满足自身的种植条件
{
for (k = 0; k < ct; ++k)//枚举i - 1行里面所有满足的状态k
{
if (!(map[i - 1]&state[k]) && !(state[k]&state[j]))
{

dp[i][state[j]] += dp[i - 1][state[k]];
}
}
}
}
}

int ans = 0;
for (i = 0; i < ct; ++i)
{
if (!(state[i]&map[n - 1]))
ans += dp[n - 1][state[i]];
ans %= MOD;
}
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: