You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

54 lines
2.3 KiB

2 years ago
#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;
}