POJ 3254
简单的状态压缩。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int Status=1<<12;
const int MOD= 100000000;
int stack[Status+10],st;
int dp[2][150][Status]; //表示当前行i,已经种了j个格,格子的状态为k时的种数。其实j个格是可以省略的,开始时没看到不种0也算一种。
int G[15],n,m,infer;
int total[Status];
void predo(){
int k,als=1<<m,confirm;
for(int i=0;i<als;i++){
confirm=3<<(m-1);
for(k=1;k<=m-1;k++){
confirm>>=1;
// cout<<confirm<<endl;
if((confirm&i)==confirm) break;
}
if(k>m-1){
// cout<<i<<endl;
stack[st++]=i;
}
// cout<<endl;
}
// cout<<endl;
// for(int i=0;i<st;i++)
// cout<<stack[i]<<endl;
// cout<<st<<endl;
}
void slove(){
int cur=0,next=1;
memset(dp,0,sizeof(dp));
dp[cur][0][0]=1;
for(int i=0;i<n;i++){
// cout<<infer<<endl;
for(int j=0;j<=infer;j++){
// cout<<"YES"<<st<<endl;
for(int k=0;k<st;k++){
/// cout<<i<<" "<<dp[cur][j][stack[k]]<<endl;
if(!dp[cur][j][stack[k]]) continue;
for(int p=0;p<st;p++){
if(j+total[stack[p]]>infer) continue;
if((stack[p]&G[i+1])!=stack[p]) continue;
if((stack[p]&stack[k])!=0) continue;
dp[next][j+total[stack[p]]][stack[p]]+=dp[cur][j][stack[k]];
dp[next][j+total[stack[p]]][stack[p]]%=MOD;
}
}
}
memset(dp[cur],0,sizeof(dp[cur]));
swap(cur,next);
}
int ans=0;
for(int i=0;i<=infer;i++)
for(int p=0;p<st;p++)
if(dp[cur][i][stack[p]]){ ans+=dp[cur][i][stack[p]]; ans%=MOD; }
printf("%d\n",ans);
}
int main(){
memset(total,0,sizeof(total));
for(int i=0;i<Status;i++){
for(int j=0;j<12;j++){
if(i&(1<<j)) total[i]++;
}
}
while(scanf("%d%d",&n,&m)!=EOF){
int t;
predo();
// cout<<st<<endl;
infer=0;
for(int i=1;i<=n;i++){
G[i]=0;
for(int j=0;j<m;j++){
G[i]<<=1;
scanf("%d",&t);
G[i]|=t;
if(t)infer++;
}
}
// cout<<infer<<st<<endl;
slove();
}
return 0;
}

浙公网安备 33010602011771号