[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;
}

浙公网安备 33010602011771号