\(f[i][j]\) 表示前 \(i\) 行且第 \(i\) 行状态为 \(j\) 的方案总数。\(j\) 的大小为 \(0 \to (1 >> n - 1)\) 。
第 \(i\) 行,种植状态为 \(j\) 的方案总数等于所有合法的 \(f[i-1][k]\) 之和。
- 状态 \(j\) 满足同一行内没有相邻的两块草地(没有共同边)。
- 状态 \(j\) 和 \(k\) 满足相邻两行的种植情况没有两块草地有共同边。
\[ f[i][j] = \sum f[i-1][k] \quad j,k \ is\ legal \]
#include<bits/stdc++.h> using namespace std; const int maxn = 1 << 12; const int mod = 1e9; int f[15][maxn], state[maxn], M[15][15], bit[15]; int n, m, ans; int main() { scanf("%d%d", &m, &n); for(int i = 1; i <= m; i++){ for(int j = 1; j <= n; j++){ scanf("%d", &M[i][j]); bit[i] = (bit[i] << 1) + M[i][j]; } } for(int i = 0; i < (1 << n); i++){ state[i] = (((i & (i << 1)) == 0) && ((i & (i >> 1)) == 0)); // = 的优先级高于 & } f[0][0] = 1; for(int i = 1; i <= m; i++){ for(int j = 0; j < (1 << n); j++){ if(state[j] && ((j & bit[i]) == j)){ for(int k = 0; k < (1 << n); k++){ if((j & k) == 0) f[i][j] = (f[i][j] + f[i - 1][k]) % mod; } } } } ans = 0; for(int i = 0; i < (1 << n); i++){ ans = (ans + f[m][i]) % mod; } printf("%d\n", ans); return 0; }