首页 > 代码库 > POJ 3254 Corn Fields 状压DP

POJ 3254 Corn Fields 状压DP

链接:http://poj.org/problem?id=3254

题意:一块M*N的田地,每小块地大小是1*1,可以种植物的标记为1,不可以种植物的标记为0,并且相邻的两块地不可以同时种植物。问题是有多少种不同的种植方案(所有地都不种也是一种种植方案)

思路:这是第一道状压DP题,从第一行更新到最后一行,每一行用一个N位的二进制数来表示该行的状态1表示该位置种了植物,0表示该位置没种植物。因为每块地只对相邻的土地能否种植有所影响,所以每一行的状态可以用前一行的状态递推得到。

资料:http://www.doc88.com/p-771373748581.html

代码:

#include<iostream>
#include<set>
#include<map>
#include<queue>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdio>
#define MOD 100000000
using namespace std;
int dp[15][40000];
bool judge(int x)
{
    if((x&(x<<1))==0)
        return 1;
    return 0;
}//函数用来判断i状态是否有相邻的土地种植了植物,如果没有,返回1
int main()
{
    int row,col,x;
    int field[15];
    memset(field,0,sizeof(field));
    memset(dp,0,sizeof(dp));
    scanf("%d%d",&row,&col);
    for(int i=0; i<row; i++)
    {
        for(int j=0; j<col; j++)
        {
            scanf("%d",&x);
            field[i]*=2;
            field[i]+=x;
        }
        //cout<<field[i]<<endl;
    }
    for(int i=0; i<(1<<col); i++)
    {
        if((field[0]&i)==i&&judge(i))
            dp[0][i]=1;
    }
    for(int i=1; i<row; i++)
    {
        for(int j=0; j<(1<<col); j++)
        {
            if((field[i]&j)==j&&judge(j))
            {
                for(int k=0; k<(1<<col); k++)
                {
                    if((k&j)==0&&judge(k))
                    {
                        dp[i][j]+=dp[i-1][k];
                        dp[i][j]%=MOD;
                    }

                }
            }
        }
    }
    int ans=0;
    for(int i=0; i<(1<<col); i++)
    {
        ans+=dp[row-1][i];
        ans%=MOD;
    }
    printf("%d\n",ans);
    return 0;
}


POJ 3254 Corn Fields 状压DP