题目大意
给出一块N∗M(1<=N,M<=12)N*M(1<=N,M<=12)N∗M(1<=N,M<=12)的矩阵,每一格都是一个正方形。有的正方形可以种草,且种的草不能相连。
如果不考虑草地的总块数,求一共有多少种种植方案
题目解析
数据很小,可以想得到状压DP
先将每一行可以种草的地方设为111,转变为状态存储,再将可行状态记录一下。
然后就枚举第iii行的状态jjj和第i−1i-1i−1行的状态kkk,如果i、ki、ki、k不冲突,则F[i][j]+=F[i−1][k]F[i][j]+=F[i-1][k]F[i][j]+=F[i−1][k]
代码
#include<bits/stdc++.h>
using namespace std;
int n,m,x;
int a[20],f[20][1<<13],b[1<<13];
bool check(int a,int b)
{
int c;
while(b)
{
c=b&-b;
if(!(a&c)) return false;
b-=b&-b;
}
return true;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>x,a[i]|=(x<<(m-j));
for(int i=0;i<(1<<m);i++)
if((i&(i<<1))==0&&(i&(i>>1))==0)
b[i]=1;
for(int i=0;i<(1<<m);i++)
if(b[i]&&check(a[1],i))
f[1][i]=1;
for(int i=2;i<=n;i++)
for(int j=0;j<(1<<m);j++)
if(b[j]&&check(a[i],j))
for(int k=0;k<(1<<m);k++)
if(b[k]&&check(a[i-1],k)&&(j&k)==0)
f[i][j]+=f[i-1][k];
x=0;
for(int i=0;i<(1<<m);i++)
x+=f[n][i];
cout<<x%100000000;
return 0;
}