经典状压dp.
f[i][S]表示在第i行且放置的集合为S的方案数
首先,S要满足没有两个1相邻.当S&(S<<1)=0
则没有两个1相邻.
然后要保证S的土地都是可以种植的,我们读入时预处理出a[i]表示第i行的肥沃土地构成的集合
,然后枚举它的子集就可以了.
考虑转移.设转移到f[i+1][T]
要满足没有1相邻,S&T=0
则没有两个1相邻.
但如果我们枚举所有T再这样判断,时间复杂度最坏$O(n\times 4^n)$,可能TLE.
我们应该只枚举S的补集的子集,这样一定保证了S&T=0
,且时间复杂度是$O(n\times 3^n)$
最后$ans=\sum_{s=0}^{2^m-1} f[n][s]$
/**********/省略快读
#define MAXN 13
const ll mod=100000000;
ll a[MAXN],f[MAXN][1<<MAXN];
bool p[1<<MAXN];
int main()
{
ll n=read(),m=read();
for(ll i=1;i<=n;++i)
{
for(ll j=1;j<=m;++j)
a[i]+=(read()<<(m-j));
}
for(ll s=0;s<(1<<m);++s)
if(s&(s<<1))p[s]=0;
else p[s]=1;
f[0][0]=1;
for(ll i=0;i<n;++i)
for(ll s=a[i];;s=(s-1)&a[i])
{
if(p[s]&&f[i][s])
{
ll tt=s^((1<<m)-1);
for(ll t=tt;;t=(t-1)&tt)
{
if(p[t]&&(t|a[i+1])==a[i+1])f[i+1][t]=(f[i+1][t]+f[i][s])%mod;
if(!t)break;
}
}
if(!s)break;
}
ll ans=0;
for(ll s=0;s<(1<<m);++s)ans=(ans+f[n][s])%mod;
printf("%lld",ans);
return 0;
}