【题目大意】一个矩阵里有很多格子,每个格子有两种状态,
可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,
在这块牧场放牛,要求两个相邻的方格不能同时放牛,
即牛与牛不能相邻。问有多少种放牛方案(一头牛都不放也是一种方案)
有个技巧就是把可放牧的与不可放牧的地方都取反 方便后面的状态比较
我看的这个博客的题解
http://blog.youkuaiyun.com/y990041769/article/details/24658419
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <cmath>
#include <stack>
#include <string>
#include <map>
#include <set>
#define pi acos(-1)
#define LL long long
#define ULL unsigned long long
#define inf 0x3f3f3f3f
#define INF 1e18
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
typedef pair<int, int> P;
const int maxn = 1e5 + 5;
const int mod = 1e8;
LL dp[13][1<<12];
int mp[13], sta[1<<12]; // 存状态的数组 satae
int n, m;
int judge(int s) // 判断二进制是否有相邻 1
{
return s & (s << 1);
}
int main(void)
{
// freopen("C:\\Users\\wave\\Desktop\\NULL.exe\\NULL\\in.txt","r", stdin);
int i, j, k, S, t, cnt;
LL ans;
while (cin >> n >> m)
{
memset(sta, 0, sizeof(sta));
memset(mp, 0, sizeof(mp));
memset(dp, 0, sizeof(dp));
for (i = 1; i <= n; i++){
for (j = 1; j <= m; j++){
scanf("%d", &t);
if (t == 0)
mp[i] += 1<<(j-1);
}
}
cnt = 0;
for (S = 0; S < (1<<m); S++)
if (!judge(S))
sta[++cnt] = S;
for (i = 1; i <= cnt; i++)
if (!(mp[1] & sta[i]))
dp[1][i] = 1;
for (i = 2; i <= n; i++){
for (j = 1; j <= cnt; j++){
if (mp[i] & sta[j]) continue; // 判断当前行 能否按 当前状态放
for (k = 1; k <= cnt; k++){
if (mp[i-1] & sta[k]) // 判断当前这个状态是否可以放在 前一行
continue; // 不符合就pass 相当于一个剪枝
if (sta[j] & sta[k]) //这个判断的是 当前状态 是否与上一行 相邻
continue;
dp[i][j] = (dp[i][j] + dp[i-1][k]) % mod;// 若符合 则当前行可按 当前状态放
}
}
}
ans = 0;
for (i = 1; i <= cnt; i++)
ans = (ans + dp[n][i]) % mod;
printf("%lld\n", ans);
}
return 0;
}