您的位置:首页 > 其它

poj 1185 炮兵阵地 状态压缩dp

2015-09-17 14:16 411 查看
题意:

良心中文题不赘述了。

分析:

状态压缩dp,每行的状态和前两行有关。

代码:

//poj 1185
//sep9
#include <iostream>
using namespace std;
int n,m;
char g[128][16];
int row_state[128][128];
int dp[128][64][64];
bool check(int row,int st)
{
	for(int j=0;j<m;++j){
		int k=((st>>j)&1);
		if(k==0) continue; 
		if(g[row][j]=='H')
			return false;
		if(j-1>=0&&((st>>(j-1))&1)==1)
			return false;
		if(j-2>=0&&((st>>(j-2))&1)==1)
			return false; 
	}
	return true;	
}

int cnt_state(int s)
{
	int cnt=0;
	for(int i=0;i<m;++i){
		cnt+=(s&1);
		s=(s>>1); 
	}	
	return cnt;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;++i)
		scanf("%s",g[i]);
	for(int i=0;i<n;++i){
		row_state[i][0]=0;
		for(int j=0;j<(1<<m);++j)
			if(check(i,j))
				row_state[i][++row_state[i][0]]=j;
	
	}
	memset(dp,0,sizeof(dp));
	for(int i=1;i<=row_state[0][0];++i){
		dp[0][i][0]=cnt_state(row_state[0][i]);
	}
	for(int i=1;i<=row_state[1][0];++i)
		for(int j=1;j<=row_state[0][0];++j){
			if(row_state[1][i]&row_state[0][j])
				continue;
			dp[1][i][j]=dp[0][j][0]+cnt_state(row_state[1][i]);
		}
	for(int row=2;row<n;++row)
		for(int i=1;i<=row_state[row][0];++i)
			for(int j=1;j<=row_state[row-1][0];++j)
				for(int k=1;k<=row_state[row-2][0];++k){
					int s=row_state[row][i];
					int s1=row_state[row-1][j];
					int s2=row_state[row-2][k];
					if(s1&s||s1&s2||s&s2)
						continue;
					dp[row][i][j]=max(dp[row][i][j],dp[row-1][j][k]+cnt_state(s));
				}
	int ans=0;
	if(n==1){
		for(int i=1;i<=row_state[0][0];++i)
			ans=max(ans,dp[0][i][0]);	
	}	
	else{
		for(int i=1;i<=row_state[n-1][0];++i)
			for(int j=1;j<=row_state[n-2][0];++j)
				ans=max(ans,dp[n-1][i][j]);
	}
	printf("%d",ans);
	return 0;	
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: