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; }