题意
一些地方可以种地(用1表示),一些地方不能(用0表示)
相邻的1不能同时种地,问有多少种可行种地方案
思路来源
https://www.bilibili.com/video/av29915579/?spm_id_from=333.788.videocard.0
题解
判 左右不相邻(now&(now<<1))==0
判 上下不相邻 (pre&now)==0
判 枚举值是当前行的子集 (now|all)==all
心得
dp[0][i]的值怎么赋值呢
看dp[1][j]怎么用到了dp[0][i]的值,按需赋值
比如说dp[1][j]应当赋1的地方,为了统一操作转移到dp[0][i]处,就赋dp[0][i]=1
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <functional>
const int INF=0x3f3f3f3f;
const int maxn=1e2+10;
const int mod=1e8;
const int MOD=998244353;
const double eps=1e-7;
typedef long long ll;
#define vi vector<int>
#define si set<int>
#define pii pair<int,int>
#define pi acos(-1.0)
#define pb push_back
#define mp make_pair
#define lowbit(x) (x&(-x))
#define sci(x) scanf("%d",&(x))
#define scll(x) scanf("%lld",&(x))
#define sclf(x) scanf("%lf",&(x))
#define pri(x) printf("%d",(x))
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int n,m;
int line[15];
ll dp[15][1<<15];
bool updown(int up,int down)
{
return (up&down)==0;
}
bool adjacant(int now)
{
return ((now)&(now<<1))==0;
}
bool subset(int a,int b)//a是b的子集
{
return (a|b)==b;
}
void init()
{
mem(line,0);
mem(dp,0);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
rep(i,1,n)
{
int num;
rep(j,0,m-1)
{
sci(num);
line[i]=(line[i]<<1)+num;
}
}
dp[0][0]=1;
rep(i,1,n)
{
rep(j,0,line[i])
{
rep(k,0,line[i-1])//利用line[0]全0,统一操作
{
if(updown(j,k)&&adjacant(j)&&subset(j,line[i]))
{
dp[i][j]+=dp[i-1][k]%mod;//k不adjacant的话,肯定没被更新,还是0,不用管
if(dp[i][j]>=mod)dp[i][j]%=mod;
}
}
}
}
ll ans=0;
rep(i,0,line[n])
{
ans+=dp[n][i];
if(ans>=mod)ans%=mod;
}
printf("%lld\n",ans);
}
return 0;
}