题目传送门:
[USACO06NOV] Corn Fields G - 洛谷
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int MOD=1e8;
int m,n;
int f[13][1<<13],a[13][13];//f[i][j]是前i行状态为j的方案数有多少a[i][j]用来储存土地状态
bool g[1<<13];//g数组用来预处理,判断状态i是否合法
int F[13];//f数组用来储存第i行的土地状态
int main()
{
cin>>m>>n;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
cin>>a[i][j];
F[i]=(F[i]<<1)+a[i][j];//将每一行的状态用f数组转存
}
}
for(int i=0;i<(1<<n);i++)
{
g[i]=(!(i&(i<<1)))&&(!(i&(i>>1)));//预处理,提前判断好状态i是否合法
}
f[0][0]=1;//全部不种也算一种情况
for(int i=1;i<=m;i++)//遍历所有行
{
for(int j=0;j<(1<<n);j++)//遍历所有情况
{
if(g[j]&&(j&F[i])==j)//用g数组判断此情况是否合法并且是否符合当前土地状态
{
for(int k=0;k<(1<<n);k++)//遍上一行的情况
{
if((k&j)==0)//如果不与本行相冲突
{
f[i][j]=(f[i][j]+f[i-1][k])%MOD;//就用此情况加上一行的情况
}
}
}
}
}
int ans=0;
for(int j=0;j<(1<<n);j++)
ans=(ans+f[m][j])%MOD;//遍历最后一行的情况相加
ans=ans%MOD;
cout<<ans;
return 0;
}