【狀壓DP】poj3254 Corn Fields
阿新 • • 發佈:2017-05-04
一行 cstring fields while state 條件 style 狀壓 ()
題意:
一塊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; }
【狀壓DP】poj3254 Corn Fields