poj 3254 Corn Fields ,狀態壓縮DP,poj3254
題目連結
題意:
一個矩陣裡有很多格子,每個格子有兩種狀態,可以放牧和不可以放牧,可以放牧用1表示,否則用0表示,在這塊牧場放牛,要求兩個相鄰的方格不能同時放牛,即牛與牛不能相鄰。問有多少种放牛方案(一頭牛都不放也是一種方案)
state[i] 表示對於一行,保證不相鄰的方案
狀態:dp[i][ state[j] ] 在狀態為state[j]時,到第i行合格可以放牛的方案數
狀態轉移:dp[i][ state[j] ] =Sigma dp[i-1][state'] (state'為合格所有狀態)
nclude<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int mod = 100000000;int state[1<<13], cnt; //對於一行,保證不相鄰的方案int dp[20][1<<13];int cur[20]; // cur[i]的值得二進位形式0表示能放,1表示不能放。int main(){ int n, m, i, j, k; scanf("%d%d", &n, &m); int M = 1<<m; cnt = 0; for(i=0; i<M; ++i) { if(i&(i<<1)) continue; //二進位有相鄰的1 state[cnt++] = i; } for(i=0; i<n; ++i) { cur[i] = 0; int x; for(j=0; j<m; ++j) { scanf("%d", &x); if(!x) cur[i] |= 1<<j; } } memset(dp, 0, sizeof dp ); for(i=0; i<cnt; ++i) if(!(cur[0]&state[i])) dp[0][state[i]] = 1; for(i=1; i<n; ++i) { for(j=0; j<cnt; ++j) if( dp[i-1][state[j]] ){ for(k=0; k<cnt; ++k) if(!(state[k]&state[j]) && !(cur[i]&state[k])) { dp[i][state[k]] = (dp[i][state[k]] + dp[i-1][state[j]]) % mod; } } } int ans = 0; for(i=0; i<cnt; ++i) ans = (ans + dp[n-1][state[i]]) % mod; printf("%d\n", ans); return 0;}