题目大意:n*m的矩阵01中1处可以种植 0处不能种植,有多少种放法,并且任意两个不能相邻
解题思路 : 对于本题用二进制表示,设f[i][st]为当前行的状态,当前行的合法状态只和上一行有关
状态转移方程:f[i][st] += f[i-1][]st'],其中st和st‘没有冲突且st没有连续的1
下边就是一些位运算操作算是积累了
st&(st>>1)为真表示有相邻的1,x&y为真表示有相邻行有冲突。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int maxn = (1<<12) + 5;
const int INF = 0x7f7f7f7f;
const int mode = 100000000;
int a[maxn], b[maxn];
long long f[13][maxn];//长见识了f[12][maxn]时c++会RE,G++就过了
int maze[15][15];
int n, m;
inline bool can(int st, int r)
{
int i = n, t = st;
if (st & (st >> 1)) return false;
while(t) {
if (t%2 == 1 && !maze[r][i]) return false;
i--;
t >>= 1;
}
return true;
}
inline bool check(int x, int y)
{
return !(x & y);
}
int main()
{
//freopen("input.txt", "r", stdin);
while (cin >> m >> n)
{
memset(f, 0, sizeof(f));
for (int i = 1; i <= m; i++)
for (int j = 1; j<= n; j++)
scanf("%d", &maze[i][j]);
int cnt = 0;
for (int st = 0; st < (1<<n); st++)//边界
{
if (can(st, 1)) {
f[1][st] = 1;
a[cnt++] = st;
}
}
for (int i = 2; i <= m; i++)
{
int tot = 0;
for (int st = 0; st < (1<<n); st++)
{
int flag = 0;
if (can(st, i))
for (int j = 0; j < cnt; j++)
if (check(st, a[j]))
{
flag = 1;
f[i][st] += f[i-1][a[j]];
}
if (flag) b[tot++] = st;
}
cnt = tot;
memcpy(a, b, sizeof(b));
}
long long ans = 0;
for (int i = 0; i < (1<<n); i++) ans += f[m][i];
cout << ans%mode << endl;
}
return 0;
}