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

  

posted @ 2015-03-31 11:10  chenjunjie1994  阅读(103)  评论(0编辑  收藏  举报