题意:一个row*col的矩阵,每个格子是0或者1,1表示土壤肥沃可以种植草地,0则不可以。在种草地的格子可以放牛,但边相邻的两个格子不允许同时放牛,问总共有多少种放牛的方法?(不放牛也算一种情况)
思路:状态压缩DP。在做了状态压缩的入门poj1185的炮兵阵地之后,再做状态DP就有章可循了,基本上很多的函数或者变量都是相通的,这里也不详解了。DP部分:dp[i][k]表示第r行处于状态k时,前r行的情况数总和。这点应该在打代码前就先明确,一开始很模糊还去求sum[i],栽了一次。
源代码:(248K, 0MS)
#include<iostream>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int MAX = 400;
const int MOD = 100000000;
int map[12];
int cnt = 0, stk[MAX];
int dp[12][MAX];
bool ok(int x){
if(x & (x<<1)) return false;
return true;
}
void findStk(int n){
for(int i = 0; i < (1<<n); i ++)
if(ok(i))
stk[cnt ++] = i;
}
int main(){
int row, col, r, c, i, j;
memset(dp, 0, sizeof(dp));
cin >> row >> col;
findStk(col);
for(r = 0; r < row; r ++)
for(c = 0; c < col; c ++){
int tmp;
cin >> tmp;
if(tmp == 0) map[r] |= (1<<c);
}
for(i = 0; i < cnt; i ++)
if(!(map[0]&stk[i]))
dp[0][i] = 1;
for(r = 1; r < row; r ++)
for(i = 0; i < cnt; i ++){
if(map[r]&stk[i]) continue;
for(j = 0; j < cnt; j ++){
if(map[r-1]&stk[j] || stk[i]&stk[j]) continue;
dp[r][i] = (dp[r][i]+dp[r-1][j])%MOD;
}
}
int ans = 0;
for(i = 0; i < cnt; i ++)
if(dp[row-1][i] != -1)
ans = (ans+dp[row-1][i])%MOD;
cout << ans << endl;
return 0;
}