54 lines
2.3 KiB
C++
54 lines
2.3 KiB
C++
#include <bits/stdc++.h>
|
||
|
||
using namespace std;
|
||
const int MOD = 1e8; // 按1e8取模
|
||
const int N = 14; // M*N个小方格,上限都是12,这里我们故意取大一点,到14.
|
||
const int M = 1 << 12; // 0~2^12-1,共2^12个状态,记录每一行的摆放状态
|
||
int n, m; // n行,m列
|
||
int g[N]; // 记录哪个位置是无法种田的,在题目中,输入的位置是0表示无法种田
|
||
vector<int> st; // 合法状态
|
||
vector<int> head[M]; // 一个状态可以转化为哪些状态(与哪此状态兼容)
|
||
int f[N][M]; // 一维:完成了第i行,二维:在状态是j(二进制状态)的情况下,值:方案数量
|
||
|
||
// 状态检查是否合法,某个状态是不是存在连续1
|
||
bool check(int x) {
|
||
return !(x & x >> 1);
|
||
}
|
||
|
||
int main() {
|
||
// 1、输入地图
|
||
scanf("%d %d", &n, &m);
|
||
for (int i = 1; i <= n; i++) // n行
|
||
for (int j = 1; j <= m; j++) { // m列
|
||
int x;
|
||
scanf("%d", &x);
|
||
if (x == 0) // 当前位置是不育的玉米地
|
||
g[i] += 1 << (j - 1); // 在对应的二进制位上标识为1,这里g[i]存放的是十进制,所以将增加的二进制转为十进制加入g[i]
|
||
}
|
||
|
||
// 2、预处理出所有合法状态
|
||
for (int i = 0; i < 1 << m; i++)
|
||
if (check(i)) st.push_back(i);
|
||
|
||
// 3、预处理出每个合法状态兼容哪些状态
|
||
for (int a : st)
|
||
for (int b : st)
|
||
if ((a & b) == 0) head[a].push_back(b);
|
||
|
||
// 4、开始DP
|
||
f[0][0] = 1; // 已经放完第0行,状态是一个也没有放,算一种方案
|
||
for (int i = 1; i <= n; i++) // 枚举每一行
|
||
for (int a : st) { // 枚举每一个合法状态
|
||
// 如果当前枚举出的a说某个位置需要种植玉米,而g[i]记录的此位置不育,那么就不能在此位置耕种
|
||
if ((g[i] & a)) continue;
|
||
// 到这里时,表明此状态完全合法,找它的所有兼容状态,所有兼容状态都可以顺利转移到a状态
|
||
for (int b : head[a])
|
||
f[i][a] = (f[i][a] % MOD + f[i - 1][b] % MOD) % MOD;
|
||
}
|
||
|
||
// 结果
|
||
int res = 0;
|
||
for (int a : st) res = (res % MOD + f[n][a] % MOD) % MOD;
|
||
printf("%d", res);
|
||
return 0;
|
||
} |