poj 3254 Corn Fields

  状态DP

  二进制题型,用0和1来确定所有的情况。

  把每一行安排的情况看成一个二进制数,如果这一行的某一列安排了一头奶牛,那么对应的二进制就是1,如果没有安排那么就是0.如果某个状态表示里出现了两个连续的1,那么这个状态永远是非法的,可以去掉,这样处理之后剩下的可能合法。

  令dp[i][j]表示第i行状态为j时有多少可能的安排方法,那么状态转移方程是:如果j是合法状态:dp[i][j]=sum{dp[i-1][k]},其中满足k&j==0。

  

#include<stdio.h>
#include<string.h>
#define maxn (1<<13)
#define mod 100000000

int n,m;
int dp[15][maxn];
bool flag[15][maxn];
int mat[15];
int mm;
void init()
{
    for(int i=1;i<=n;i++)
    for(int j=0;j<=mm;j++)
    {
        flag[i][j]=true;
        if((~mat[i]&j)||(j&(j<<1)))
        flag[i][j]=false;
    }
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(dp,0,sizeof(dp));
        memset(mat,0,sizeof(mat));
        int num;
        for(int i=1;i<=n;i++)
        for(int j=m-1;j>=0;j--)
        {
            scanf("%d",&num);
            if(num==1)mat[i]|=(1<<j);
        }
        mm=(1<<m)-1;
        init();
        for(int i=0;i<=mm;i++)
        if(flag[n][i]) dp[n][i]=1;
        int i,j;
        for(i=n-1;i>=1;i--)
        {
            for(j=0;j<=mm;j++)
            {
               if(!flag[i][j]) continue;
               for(int k=0;k<=mm;k++)
               {
                   if(!flag[i+1][k]) continue;
                   if(!(j&k))
                   dp[i][j]+=dp[i+1][k];
               }
               dp[i][j]%=mod;
            }
        }
        int ans=0;
        for(i=0;i<=mm;i++)
        ans+=dp[1][i]%mod;
        ans%=mod;
        printf("%d\n",ans);
    }
}
View Code

 

posted @ 2013-08-17 14:16  yongren1zu  阅读(119)  评论(0编辑  收藏  举报