BZOJ 1725 Corn Fields
状压DP
DP[i][j]表示已放完i行,第i行放置状态为j的方案数
预处理出所有满足一行中无两格相邻的放置方案
列数为12时这个方案数少于400
枚举方案转移,需要满足与上一行无交且是Map(可行格)的子集
#include <cstdio>
const int MAXN=12;
const int MAXM=12;
const int MOD=100000000;
int N, M, Val;
int Map[MAXN];
int DP[MAXN][1<<MAXM];
bool Test(int a){
bool ret=true;
for(int i=0, p=0;i<M;++i, a>>=1){
if(p>0 && (a&1)) {ret=false;break;}
p=a&1;
}
return ret;
}
int Put[1<<MAXM], Pcnt;
int main(){
scanf("%d%d", &N, &M);
for(int i=0;i<N;++i){
Map[i]=0;
for(int j=0, a;j<M;++j){
scanf("%d", &a);
if(a>0) Map[i]+=(1<<j);
}
}
for(int i=(1<<M)-1;i>=0;--i)
if(Test(i))
Put[++Pcnt]=i;
//for(int i=1;i<=Pcnt;++i)
// printf("%d\n", Put[i]);
for(int i=1;i<=Pcnt;++i){
if((Put[i]&Map[0])==Put[i]){
DP[0][Put[i]]=1;
}
}
for(int i=0;i+1<N;++i){
for(int j=(1<<M)-1;j>=0;--j){
if(DP[i][j]<=0) continue;
for(int p=1;p<=Pcnt;++p){
if((Put[p]&Map[i+1])==Put[p] && (Put[p]&j)==0){
DP[i+1][Put[p]]+=DP[i][j];
if(DP[i+1][Put[p]]>=MOD) DP[i+1][Put[p]]-=MOD;
}
}
}
}
int Ans=0;
for(int j=(1<<M)-1;j>=0;--j){
Ans+=DP[N-1][j];
if(Ans>=MOD) Ans-=MOD;
}
printf("%d\n", Ans);
return 0;
}