POJ 1185

经典的状态压缩DP题了。做了前面两题,就不感觉难了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
int stack[1<<10],cst;
int dp[2][1<<10][1<<10];
int G[105],tot[1<<10];
char str[15];
int n,m;

void Init(){
	int alt=(1<<10);
	memset(tot,0,sizeof(tot));
	for(int i=0;i<alt;i++){
		int st=1;
		for(int j=0;j<10;j++){
			st=1<<j;
			if(st&i) tot[i]++;
		}
//		cout<<tot[i]<<endl;
	}
}

void predo(){
	cst=0;
	int alt=1<<m;
	int l1,l2,r1,r2;
	for(int i=0;i<alt;i++){
		bool flag=true;
		for(int j=0;j<m;j++){
			int st=1<<j;
			if(st&i){
				l1=st<<1,l2=st<<2;
				r1=st>>1,r2=st>>2;
				if(l1&i){flag=false; break;}
				if(l2&i){flag=false; break;}
				if(r1&i){flag=false; break;}
				if(r2&i){flag=false; break;}
			}
		}
		if(flag) stack[cst++]=i;
	}
//	cout<<cst<<endl;
}

void slove(){
	memset(dp,-1,sizeof(dp));
	int cur=0,next=1;
	dp[cur][0][0]=0;
	for(int i=0;i<n;i++){
		for(int j=0;j<cst;j++){
			for(int k=0;k<cst;k++){
				if(dp[cur][j][k]==-1) continue;
				for(int p=0;p<cst;p++){
			//		cout<<"YES"<<endl;
					if((stack[p]&G[i+1])!=stack[p]) continue;
					if(i>=1)
						if(stack[p]&stack[j]) continue;
					if(i>=2) if(stack[p]&stack[k]) continue;
					dp[next][p][j]=max(dp[next][p][j],dp[cur][j][k]+tot[stack[p]]);
				}
			}
		}
		memset(dp[cur],-1,sizeof(dp[cur]));
		swap(cur,next);
	}
	int ans=0;
	for(int i=0;i<cst;i++){
		for(int j=0;j<cst;j++)
		ans=max(ans,dp[cur][i][j]);
	}
	printf("%d\n",ans);
}

int main(){
	Init();
	while(scanf("%d%d",&n,&m)!=EOF){
		predo();
		for(int i=1;i<=n;i++){
			scanf("%s",str);
			G[i]=0;
			for(int j=0;j<m;j++){
				G[i]<<=1;
				if(str[j]=='P') G[i]|=1;
			}
		}
		slove();
	}
	return 0;
}

  

posted @ 2015-03-31 19:55  chenjunjie1994  阅读(120)  评论(0编辑  收藏  举报