pku 3254 Corn Fields 状态DP

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[N],dp[N][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;
}

 

posted @ 2012-08-13 17:33  E_star  阅读(193)  评论(0编辑  收藏  举报