/* 状态压缩+动态规划 题意:M*N的一块地,进行划分,要求划分后各区域不能有公共边,可以一块也不选择。题意我也不懂,根据后面所给的测试数据,才有了一些了解。 思路: 状态:d[i][s]表示第i行状态为s时所有的方案数。 状态转移:d[i][a]=sum(d[i-1][b]),a、b的关系为a中为1的位置b为0;a的判断有两个条件: ①与图进行匹配,图中为0的位置不能为1 ②两个1不能相连 初态:d[0][]都为1//如何定初态?只要让第一组测试数据正确即可。 末态:d[M][0] 注意: ①,找了好久才找出的错误,位运算一般不要进行==操作,而且一般不为1 */ //#define TEST #include <cstdio> #include <cstring> const int nMax=13,INF=100000000; int M,N; int map[nMax][nMax]; long long d[nMax][1<<nMax]; bool check1(int row,int s) { bool ok=1; for(int i=0;i<N;i++) { //printf("%d %d\n",map[row][i]==0,(s & (1<<i))==1); if(map[row][i]==0 && (s & (1<<i)))//①(s & (1<<i))==1 { ok=0; break; } } for(int i=0;ok && i<N-1;i++) if((s & (1<<i)) && (s & (1<<(i+1)))) { ok=0; break; } return ok; } bool check2(int row,int s1,int s2) { bool ok=1; for(int i=0;i<N;i++) if((s1 & (1<<i)) && (s2 & (1<<i))) { ok=0; break; } return ok; } void dp() { int z=1<<N; memset(d,0,sizeof(d)); for(int i=0;i<=M;i++) { for(int s=0;s<z;s++) if(check1(i,s)) { if(i==0) d[i][s]=1; else for(int s0=0;s0<z;s0++) { if(check2(i,s,s0)) { d[i][s]+=d[i-1][s0]; } } d[i][s]%=INF; if(i==M) break; #ifdef TEST printf("%d %d %d\n",i,s,d[i][s]); #endif } } } int main() { //freopen("f://data.in","r",stdin); scanf("%d %d",&M,&N); for(int i=0;i<M;i++) for(int j=0;j<N;j++) scanf("%d",&map[i][j]); dp(); printf("%lld\n",d[M][0]); return 0; }