#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<ctime>
#include<algorithm>
#define RG register
#define maxn 1<<14
#define MOD 100000000
using namespace std;
int n,m,ans=0;
int dp[13][maxn];
int line[maxn];
inline int read()
{
int s=0,k=1;
char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if(ch=='-') k=-1,ch=getchar();
while(ch>='0'&&ch<='9') s=s*10+(ch-'0'),ch=getchar();
return s*k;
}
inline int check1(int x)
{
if(x&x<<1) return false;
return true;
}
inline int check2(int x,int y)
{
if(x&line[y]) return false;
return true;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
ans=0;
int minn=1<<m;
memset(dp,0,sizeof(dp));
memset(line,0,sizeof(line));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
int num=read();
if(num==0) line[i]+=1<<(m-j);
}
for(int i=0;i<minn;i++) if(check1(i)&&check2(i,1)) dp[1][i]=1;
for(int i=2;i<=n;i++)
for(int k=0;k<minn;k++)//枚举当前行状态
{
if(check1(k)&&check2(k,i))//判断这个状态合法以及这个状态与当前行要求状态合法
{
for(int j=0;j<minn;j++)//枚举前一行状态
{
if(check1(j)&&check2(j,i-1))//判断这个状态合法以及这个状态与当前行要求状态合法
{
if((j&k)==0)
dp[i][k]=(dp[i][k]+dp[i-1][j])%MOD;
}
}
}
}
for(int i=0;i<minn;i++) ans=(ans+dp[n][i])%MOD;
printf("%d\n",ans%MOD);
}
return 0;
}
这道题其实思路很容易, 我们可以轻松地推出状态转移方程为: F[i][k]=F[i-1][∑1--1<<M] 再就只需要利用位运算,进行状态判断合法就可以了。