题意:在由方格组成的矩形里面种草,相邻方格不能都种草,有障碍的地方不能种草,问有多少种种草方案(不种也算一种方案)。
分析:方格边长范围只有12,用状态压缩dp好解决。
预处理:每一行的障碍用一个状态保存好 每一行不考虑障碍的所有符合要求的状态保存好 第一行的方案数记录好。
然后一行一行递推,每一行只与上一行有关。
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <climits>//形如INT_MAX一类的
#define MAX 100005
#define INF 0x7FFFFFFF
#define mod 100000000
//#pragma comment(linker, "/STACK:36777216") ///传说中的外挂
using namespace std; int map[15][15];
int dp[15][1 << 12];
int buff[1 << 12]; //保存每一行不考虑障碍的状态
int bar[15]; //保存每一行的障碍的状态
int n,m,sum,ans; void getbuff() {
int total = 1 << m;
for(int i=0; i<total; i++) {
if(i & (i >> 1)) continue;
buff[sum++] = i;
}
} void solve() {
for(int i=1; i<n; i++) {
for(int j=0; j<sum; j++) {
if(buff[j] & bar[i]) continue;
for(int k=0; k<sum; k++) {
if(buff[j] & buff[k]) continue;
if(buff[k] & bar[i-1]) continue; //注意也要判冲突与否
dp[i][buff[j]] = (dp[i][buff[j]] + dp[i-1][buff[k]]) % mod;
}
}
}
ans = 0;
for(int j=0; j<sum; j++) {
ans = (ans + dp[n-1][buff[j]]) % mod;
}
}
int main(){
scanf("%d%d",&n,&m);
memset(dp,0,sizeof(dp));
memset(bar,0,sizeof(bar));
sum = 0;
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
scanf("%d",&map[i][j]);
if(map[i][j] == 0) {
int move = m - j - 1;
bar[i] += 1 << move;
}
}
}
getbuff();
for(int j=0; j<sum; j++) {
if(buff[j] & bar[0]) continue; // 注意
dp[0][buff[j]] = 1;
}
solve();
printf("%d\n",ans);
return 0;
}