问题描述
Farmer John买了一片土地,可以表示为一片由方块组成的网格,长度为M,宽度为N(1 <= M, N <= 12)。现在FJ要在地里种上一些玉米让他的奶牛们直接在地里食用。FJ知道他的这片土地有些地方很贫瘠,没有办法种玉米;并且奶牛们不喜欢挨在一起吃玉米,所以不能在相邻的两块地上种玉米。请帮助FJ计算一下所有可能的种玉米的方案数。注意,结果输出对于100,000,000的余数,一棵玉米也不中也算是一种方案。
把每一行的状态存入 。
表示 行,并且第 行状态为 时的合法方案数。
考虑状态的转移,既然要求转移合法,我们就来考虑一下合法的条件:
当前枚举的状态 与对应的 不冲突,
当前枚举的状态 与上一层的某状态 不冲突,
当前枚举的状态自身没有连续的 ,
如果枚举出来的当前层状态 与上一层状态 满足上面三个条件,就可以进行累加转移:
然后初始化 即可。
#include <bits/stdc++.h>
using namespace std;
const int Mod=1e8;
const int Inf=1e9;
int DP[13][1<<13];
int N,M,T,Ans,Line[13],Map[13][13];
int main(){
int I,J,K;
scanf("%d%d",&N,&M);T=(1<<M)-1;
for(I=1;I<=N;I++){
for(J=1;J<=M;J++){
scanf("%d",&Map[I][J]);
if(Map[I][J]==1){
Line[I]=Line[I]|(1<<(J-1));
}
}
}
for(I=0;I<=T;I++){
if((I|Line[1])==Line[1]&&((I>>1)&I)==0&&(I&(I<<1))==0){
DP[1][I]=1;
}
}
for(I=2;I<=N;I++){
for(J=0;J<=T;J++){
for(K=0;K<=T;K++){
if((J|Line[I])==Line[I]&&(J&K)==0&&((J>>1)&J)==0&&(J&(J<<1))==0){
DP[I][J]=(DP[I][J]+DP[I-1][K])%Mod;
}
}
}
}
for(I=0;I<=T;I++){
Ans=(Ans+DP[N][I])%Mod;
}
printf("%d",Ans);
return 0;
}