[HNOI2007] 神奇游乐园 题解

题目让求最大加权回路,容易想到插头 \(dp\)。其余的就很常规了。

#include<bits/stdc++.h>
using namespace std;
const int N=2205,M=105;
int n,m,mp[N][M][10],c[M][10];
bool vis[N][M][10];int st[10];
int hs(vector<int>g){
	int re=0;
	for(auto y:g) re=re*3+y;
	return re;
}int dfs(int x,int y,vector<int>g){
	if(x>n) return -1e9;
	if(y>m){
		if(g[m]||x==n) return -1e9;
		for(int i=m;i;i--) swap(g[i],g[i-1]);
		return dfs(x+1,1,g);
	}int hg=hs(g),ans=0;
	if(vis[hg][x][y]) return mp[hg][x][y];
	vis[hg][x][y]=1;
	if(!g[y-1]&&!g[y]){
		ans=dfs(x,y+1,g),g[y-1]=1,g[y]=2;
		ans=max(ans,dfs(x,y+1,g)+c[x][y]);
	}else if(!g[y-1]||!g[y]){
		ans=dfs(x,y+1,g),swap(g[y-1],g[y]);
		ans=max(ans,dfs(x,y+1,g))+c[x][y];
	}else if(g[y-1]==1&&g[y]==2){
		int sum=0;
		for(int i=0;i<=m;i++) sum+=(g[i]>0);
		ans=(sum>2?-1e9:c[x][y]);
	}else if(g[y-1]==2&&g[y]==1)
		g[y-1]=g[y]=0,ans=dfs(x,y+1,g)+c[x][y];
	else if(g[y-1]==1&&g[y]==1){
		for(int i=0,tp=0;;i++){
			if(g[i]==2){
				if(st[tp]!=y) tp--;
				else{g[i]=1;break;}
			}else if(g[i]) st[++tp]=i;
		}g[y-1]=g[y]=0,ans=dfs(x,y+1,g)+c[x][y];
	}else if(g[y-1]==2&&g[y]==2){
		for(int i=0,tp=0;;i++){
			if(g[i]==2){
				if(i!=y-1) tp--;
				else{g[st[tp]]=2;break;}
			}else if(g[i]) st[++tp]=i;
		}g[y-1]=g[y]=0,ans=dfs(x,y+1,g)+c[x][y];
	}return mp[hg][x][y]=ans;
}int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m;vector<int>g;
	for(int i=0;i<=m;i++) g.push_back(0);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++) cin>>c[i][j];
	cout<<dfs(1,1,g);
	return 0;
}
posted @ 2025-04-06 08:48  长安一片月_22  阅读(13)  评论(0)    收藏  举报