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;

}

 

你可能感兴趣的:(Field)