题意:在由方格组成的矩形里面种草,相邻方格不能都种草,有障碍的地方不能种草,问有多少种种草方案(不种也算一种方案)。
分析:方格边长范围只有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 ",ans); return 0; }