[luogu 2704][poj 1185] 炮兵阵地 {状态压缩dp}

版权声明:~~~感谢支持! https://blog.csdn.net/qq_39897867/article/details/88903315

题目

https://www.luogu.org/problemnew/show/P2704


解题思路

f [ i ] [ j ] [ k ] i i 2 j i 1 k 设f[i][j][k]表示目前为第i行,i-2行第j个合法状态,i-1行第k个合法状态 时的炮兵总数。
f [ i ] [ l ] [ k ] = m a x ( f [ i ] [ l ] [ k ] , f [ i 1 ] [ k ] [ j ] + s u m [ l ] ) s u m [ l ] l f[i][l][k]=max(f[i][l][k],f[i-1][k][j]+sum[l])\\ sum[l]{\color{red}表示状态为l时的炮兵总数}


代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define rep(i,x,y) for (register int i=x;i<=y;i++)
using namespace std; 
const int N=110,MAXN=(1<<10);
int n,m,ans,s[MAXN],t[N],tot,a[MAXN]; 
char c; 
bool check(int x){
	int ant=0; 
	while (x){
		if ((x&1)&&ant) return 0; 
		if (x&1) ant=3;
		if (ant) ant--; 
		x>>=1;
	}
	return 1; 
}
int lowbit(int x){
	int ant=0; 
	while (x){
		ant+=(x&1); 
		x>>=1;
	}
	return ant; 
}
int main(){
	scanf("%d%d\n",&n,&m); 
	rep(i,1,n) rep(j,1,m) cin>>c,t[i]=(t[i]<<1)+(c=='H');
	int M=1<<m; 
	rep(i,0,M-1) if (check(i)) s[++tot]=i,a[tot]=lowbit(i); 
	int f[N][tot+1][tot+1]; memset(f,0,sizeof(f)); 
	rep(i,1,n) 
	 rep(j,1,tot) if (i==1||!(s[j]&t[i-2])){
	  rep(k,1,tot) if (!(s[k]&t[i-1])&&!(s[j]&s[k])) {
	   rep(l,1,tot) if (!(s[j]&s[l])&&!(s[k]&s[l])&&!(s[l]&t[i])){
	 	f[i][l][k]=max(f[i][l][k],f[i-1][k][j]+a[l]); 	
	   } 
	  }
	}
	rep(i,1,tot) rep(j,1,tot) ans=max(ans,f[n][i][j]); 
	printf("%d",ans); 
}

猜你喜欢

转载自blog.csdn.net/qq_39897867/article/details/88903315