思路:一行有m列那么每一列就有 个状态,我们先列出这些状态中可行的状态有多少,又因为有些地方我们不能放,所以在检测状态正确性时,需要记录当前行那些地方能不能放的状态,那么在输入时,如果为0那么我们吧这个当前行的这一列置为1,在后面与每一行的可行状态检测时进行&运算如果为0那么说明当前状态合法。每一行的状态都有上一行得来,方案数也是一样,dp[i][j]表示前i行中第i行的状态是j的时候的方案数。那么
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#include<iostream>
#include<vector>
#include<queue>
#include<stack>
//#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define SIS std::ios::sync_with_stdio(false)
#define space putchar(' ')
#define enter putchar('\n')
#define lson root<<1
#define rson root<<1|1
typedef pair<int,int> PII;
const int mod=100000000;
const int N=2e5+10;
const int M=1e3+10;
const int inf=0x7f7f7f7f;
const int maxx=2e5+7;ll gcd(ll a,ll b)
{return b==0?a:gcd(b,a%b);
}ll lcm(ll a,ll b)
{return a*(b/gcd(a,b));
}template <class T>
void read(T &x)
{char c;bool op = 0;while(c = getchar(), c < '0' || c > '9')if(c == '-')op = 1;x = c - '0';while(c = getchar(), c >= '0' && c <= '9')x = x * 10 + c - '0';if(op)x = -x;
}
template <class T>
void write(T x)
{if(x < 0)x = -x, putchar('-');if(x >= 10)write(x / 10);putchar('0' + x % 10);
}
ll qsm(int a,int b,int p)
{ll res=1%p;while(b){if(b&1) res=res*a%p;a=1ll*a*a%p;b>>=1;}return res;
}int n,m,tot;
int state[N];
int bkup[N];
int dp[1005][1005];
void init()
{tot=1;int sta=1<<m;for(int i=0;i<sta;i++){if((i&(i<<1))==0)///检测有没有连续的1{state[tot++]=i;}}tot--;}int main()
{while(~scanf("%d%d",&n,&m)){init();memset(bkup,0,sizeof bkup);for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){int x;scanf("%d",&x);if(x==0)bkup[i]=bkup[i]|(1<<(m-j));//将第m-j位变成1}}memset(dp,0,sizeof dp);for(int i=1;i<=tot;i++){if((state[i]&bkup[1])==0)///检测状态正确性{dp[1][i]=1;}}for(int i=2;i<=n;i++){for(int j=1;j<=tot;j++){if((state[j]&bkup[i])==0)///当前这一行的状态可以成功{for(int k=1;k<=tot;k++)///累加上一行的可行数{if(((state[k]&bkup[i-1])==0)&&((state[k]&state[j])==0))///判断当前行状态是否与上一行冲突{dp[i][j]=(dp[i][j]+dp[i-1][k])%mod;}}}}}int ans=0;for(int i=1;i<=tot;i++){ans=(ans+dp[n][i])%mod;}printf("%d\n",ans);}return 0;
}