'commit'
This commit is contained in:
54
TangDou/AcWing/StateCompression/327.cpp
Normal file
54
TangDou/AcWing/StateCompression/327.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user