给出
n
,
m
≤
12
n,m\leq12
n,m≤12的田地,一些位置是
1
1
1表示可以种草,一些位置是
0
0
0表示不可以种,然后要求出所有的种植方案,满足任意两个种草的位置都不会相邻。
状态压缩的好题。处理出每行的状态,同时也预处理所有不出现相邻位置的状态。
枚举到当前的这一行的时候,合法的状态是当前状态的子集同时也要满足不出现相邻的位置,然后再枚举上一行的状态,若上一行的状态也合法且与这一层的状态没有交集。那么就可以转移。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int mod=1e8;
const int N=13;
int a[N][N];
int s[1<<12],g[1<<12];
ll f[N][1<<12];
int main() {
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
scanf("%d",&a[i][j]);
if(a[i][j]==1) s[i]|=(1<<(m-j));
}
}
for(int i=0;i<(1<<m);i++) {
if((i&(i<<1))||(i&(i>>1))) g[i]=0;
else g[i]=1;
}
f[0][0]=1;
for(int i=1;i<=n;i++) {
for(int j=0;j<(1<<m);j++) {
if(g[j]==1&&(j&s[i])==j) {
for(int k=0;k<(1<<m);k++) {
if(g[k]==1&&(j&k)==0) {
f[i][j]=(f[i][j]+f[i-1][k])%mod;
}
}
}
}
}
ll ans=0;
for(int i=0;i<(1<<m);i++) {
if(g[i]==1) {
ans=(ans+f[n][i])%mod;
}
}
printf("%lld\n",ans);
return 0;
}