题目大意:一个row*col的矩阵,每个格子是0或者1,1表示土壤肥沃可以种植草地,0则不可以。在种草地的格子可以放牛,但边相邻的两个格子不允许同时放牛,问总共有多少种放牛的方法?(不放牛也算一种情况)
解题思路:状态压缩DP。dp[r][k]表示第r行处于状态k时,前r行的情况数总和
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <string>
#include <map>
#include <stack>
#include <list>
#include <set>
using namespace std;
const int maxn = 1<<12;
const int MOD = 100000000;
int dp[15][maxn],state[maxn],mp[15];
int cnt;
bool ok(int x)
{
if(x & (x<<1)) return false;
return true;
}
void findState(int n)
{
for(int i = 0; i < (1<<n); i++)
{
if(ok(i))
state[cnt++] = i;
}
}
int main()
{
int n,m,x;
while(scanf("%d%d",&n,&m) != EOF)
{
memset(dp,0,sizeof(dp));
memset(mp,0,sizeof(mp));
cnt = 0;
findState(m);
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
scanf("%d",&x);
if(x == 0)
mp[i] |= (1<<(j-1));//翻转01,便于判断
}
for(int j = 0; j < cnt; j++)//初始化第一行
if(!(mp[1]&state[j]))
dp[1][j] = 1;
}
for(int r = 2; r <= n; r++)
{
for(int j = 0; j < cnt; j++) //r行的状态
{
if(mp[r]&state[j]) continue;
for(int k = 0; k < cnt; k++) //r-1行的状态
{
if((mp[r-1]&state[k]) || (state[k]&state[j])) continue;
dp[r][j] = (dp[r][j]+dp[r-1][k])%MOD;
}
}
}
int ans = 0;
for(int i = 0; i < cnt; i++)
{
ans = (ans+dp[n][i])%MOD;
}
printf("%d\n",ans);
}
return 0;
}