poj 3254 Corn Fields(状态压缩dp)

来源:互联网 发布:mac win触摸板难用 编辑:程序博客网 时间:2024/06/03 04:19

状态压缩dp入门。
参考:http://www.cnblogs.com/BlackStorm/p/4706243.html
我的理解都在注释里。

#include <stdio.h>const int mod = 1e8;int row[13],rec[377],dp[13][377];int main(){    int x=1<<12, k=0;    //先不考虑哪些土地能种植,哪些土地不能种植    //枚举出一行的所有合法状态,即两头牛不相邻    for(int i = 0; i < x; ++i)    {        if(!(i&(i<<1)))            rec[k++]=i;    }    rec[k]=x;    int M,N,t;    scanf("%d%d",&M,&N);    //输入土地的状态,即哪些能种植,哪些不能种植    //把状态翻转过来,0表示可种植,1表示不可种植    //这样只有当行种植状态和行状态相与为0,这个种植状态才在该行有效,    //因为如果种在了不肥沃的格子上,相位与会保留位1,结果不为0。    for(int i = 0; i < M; ++i)        for(int j = 0; j < N; ++j)        {            scanf("%d",&t);            row[i] = (row[i]<<1)|!t;        }    x=1<<N;    //处理第一行    for(int i = 0; rec[i]<x; ++i)    {        if(!(row[0]&rec[i]))            dp[0][i] = 1;    }     //枚举1-M行的状态    for(int r = 1; r<M; ++r)    {        //枚举当前行上一行的所有可能状态        for(int i = 0; rec[i]<x; ++i)        {            //判断这个状态能否合法种植在上一行            if(!(row[r-1]&rec[i]))            {                //再枚举当前行所有可能状态                for(int j = 0; rec[j]<x; ++j)                    //判断在当前行能否合法种植                    if(!(row[r]&rec[j]))                        //载判断与上一行是否冲突                        if(!(rec[i]&rec[j]))                            dp[r][j] = (dp[r][j]+dp[r-1][i])%mod;            }        }    }    int r = M-1;    for(int i = 1; rec[i]<x; ++i)        dp[r][0] = (dp[r][0]+dp[r][i])%mod;    printf("%d\n",dp[r][0]);    return 0;}
原创粉丝点击