【状压DP】poj3254 Corn Fields
题意:
一块n*m的田,1表示这个地方可以种植,0代表这个地方不能种植。植物种植还必须满足两株植物不能相邻(横竖都不行)。问共有几种种植方法,而且当什么都不种时认为是一种方法。
解题思路:
种植用1表示,不种植用0表示。每一行的情况就可以用一个二进制数state来存储。state的范围是 [0 ~ 1<< state).
dp[i][state]表示第i行状态为state的情况下满足条件的数目。
状态转移方程为:dp[i][state] += dp[i-1][pre_state];这个state和pre_state必须满足意义所给的条件,即左右不相邻,上下不相邻。那么 第i行状态为state的情况为第i-1行所有满足条件的状态为pre_state相加而成。
最后的答案为最后一行所有状态的情况和相加而得。
代码如下:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int dp[15][1<<15]; bool is[15][15]; int n,m; const int MOD = 1e8; bool check(int x,int state) { if((state&(state<<1))) return false; for(int i=1;i<=m;i++) { if(!is[x][i]) { if(((1<<(m-i))& state)!=0) return false; } } return true; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) for(int j = 1;j<=m;j++) scanf("%d",&is[i][j]); dp[0][0]=1; long long ans=0; for(int i=1;i<=n;i++) { for(int j=0;j<(1<<m);j++) { if(check(i,j)) { for(int k=0;k<(1<<m);k++) { if(!(k&j))dp[i][j]+=dp[i-1][k]; } } if(i==n)ans=(ans+dp[i][j])%MOD; } } printf("%lld\n",ans); } return 0; }