种植方案
题目链接:ybt高效进阶5-5-1
题目大意
给你一个 n*m 的矩阵,有一些点不可以放东西,有些放不放都行。
然后问你有多少种放的方案,使得满足不会有两个东西相邻。
思路
明显的状压。
想了想发现一行一行搞复杂度有点危,可能要压状态。
然后不想压状态的我就写了个轮廓线 DP,跑得飞快。
ヾ(✿゚▽゚)ノ好耶~
代码
#include<cstdio>
#include<cstring>
#define mo 100000000
using namespace std;
int n, m, f[2][4100], now, nxt, ans;
bool a[12][12];
int main() {
scanf("%d %d", &n, &m);
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
scanf("%d", &a[i][j]);
now = 0; nxt = 1;
f[now][0] = 1;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++) {
for (int fr = 0; fr < (1 << m); fr++) {
int to = fr;//不选
if ((to >> j) & 1) to ^= (1 << j);
f[nxt][to] += f[now][fr];
if (f[nxt][to] >= mo) f[nxt][to] -= mo;
to = fr;//选
if ((to >> j) & 1) continue;
if (!a[i][j]) continue;
if ((to >> (j - 1)) & 1) continue;
to |= (1 << j);
f[nxt][to] += f[now][fr];
if (f[nxt][to] >= mo) f[nxt][to] -= mo;
}
memset(f[now], 0, sizeof(f[now]));
now = nxt;
nxt = now ^ 1;
}
for (int i = 0; i < (1 << m); i++)
ans = (ans + f[now][i]) % mo;
printf("%d", ans);
return 0;
}