洛谷-炮兵阵地(状压DP)

原题链接
在这里插入图片描述
代码:

#include <bits/stdc++.h>
#define ll long long
#define IOS std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
template<class T> inline void read(T &x){
    
    
    x=0; register char c=getchar(); register bool f=0;
    while(!isdigit(c))f^=c=='-',c=getchar();
    while(isdigit(c))x=x*10+c-'0',c=getchar(); if(f)x=-x;
}
using namespace std;

int a[105];
int num[105],st[105][1025];
int dp[101][1025][1025];
int vis[105][1025];
int main()
{
    
    
	int n,m;
	char s[20];
	scanf("%d %d",&n,&m);
	int k=1<<m;//状态总数
	for(int i=1;i<=n;i++)
    {
    
    
        scanf("%s",s);
        for(int j=0;j<m;j++)
		{
    
    
			if(s[j]=='P')
			{
    
    a[i]+=(1<<j);}
		}
	}
	for(int i=1;i<=n;i++)//initialization
	{
    
    
		for(int j=0;j<k;j++)
		{
    
    
			if((j|a[i])!=a[i])continue;
			if((j<<1)&j)continue;
			if((j<<2)&j)continue;
			st[i][num[i]]=j;
			for(int e=0;e<m;e++){
    
    
				if((j>>e)&1){
    
    
					vis[i][num[i]]++;
				}
			}
			num[i]++;
		}
	}
	int ans=-99999999;
	for(int i=0;i<num[1];i++){
    
    //预处理第一行数据
		dp[1][i][0]=vis[1][i];
		ans=max(ans,dp[1][i][0]);
	}
	for(int i=0;i<num[2];i++){
    
    //预处理第二行
		for(int j=0;j<num[1];j++){
    
    
			if(st[2][i]&st[1][j])continue;
			dp[2][i][j]=max(dp[2][i][j],dp[1][j][0]+vis[2][i]);
            ans=max(ans,dp[2][i][j]);
		}
	}
	for(int i=3;i<=n;i++){
    
    //循环行数
		for(int j=0;j<num[i];j++){
    
    //循环该行的合法状态
			for(int s1=0;s1<num[i-1];s1++){
    
    //循环上一行的合法状态
				for(int s2=0;s2<num[i-2];s2++){
    
    //循环上两行的合法状态
					if(st[i-1][s1]&st[i-2][s2])continue;
					if(st[i][j]&st[i-1][s1])continue;
					if(st[i][j]&st[i-2][s2])continue;
					dp[i][j][s1]=max(dp[i][j][s1],dp[i-1][s1][s2]+vis[i][j]);
					ans=max(ans,dp[i][j][s1]);
				}
			}
		}
		//cout<<ans<<endl;
	}
	printf("%d\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43781431/article/details/107605780