Poj 1185 炮兵阵地

简单的状压dp


因为炮兵的攻击范围是两格,所以状态要多开一维


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn = 200;
const int log = 11;

int dp[maxn][maxn][maxn];
char Map[maxn][log];
int bmap[maxn];

void cTb(int n,int m){
	for(int i=0;i<n;i++){
		int t = 0;
		for(int j=0;j<m;j++){
			t = t * 2 + (Map[i][j] == 'H'?1:0);
		}
		bmap[i] = t;
	}
}

bool juder(int a,int b,int c){
	return (a&b)==0 && (b&c)==0 && (c&a)==0;
}

bool able(int x){
	return juder(x,x<<1,x<<2);
}

int calp(int x){
	int ret = 0;
	while(x){
		ret += x%2;
		x/=2;
	}
	return ret;
}

int state[maxn];

int main(){
	int n,m;
	int lener = 0;
	for(int i=0;i<(1<<log);i++){
        if(able(i))
            state[lener++] = i;
	}
	while(~scanf("%d %d",&n,&m)){
		for(int i=0;i<n;i++){
			scanf("%s",Map[i]);
		}
		memset(dp,0,sizeof(dp));
		cTb(n,m);
		int len = 1<<m;
		for(int i=0;state[i]<len;i++){
			if((state[i]&bmap[0])==0){
				dp[0][i][0] = max(dp[0][i][0],calp(state[i]));
            }
		}
		if(n>1){
			for(int i=0;state[i]<len;i++){
				for(int j=0;state[j]<len;j++){
					if((state[i]&state[j])!=0 || (state[j]&bmap[1])!=0) continue;
					dp[1][j][i] = max(dp[1][j][i],calp(state[j])+dp[0][i][0]);
				}
			}
		}
		if(n>2){
			for(int i=2;i<n;i++){
				for(int j=0;state[j]<len;j++){
					for(int k=0;state[k]<len;k++){
						for(int l=0;state[l]<len;l++){
							if((state[l]&bmap[i])==0 &&  juder(state[j],state[k],state[l]))
								dp[i][l][k] = max(dp[i][l][k],calp(state[l])+dp[i-1][k][j]);
						}
					}
				}
			}
		}
		int ans = 0;
		for(int i=0;state[i]<len;i++){
			for(int j=0;state[j]<len;j++){
				ans = max(ans,dp[n-1][i][j]);
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}


你可能感兴趣的:(Poj 1185 炮兵阵地)