容易发现一定能构造出一种正确答案,满足先横着走到头再向下走,或者先向下走再横着走到头是最长路。
那么可以想到枚举两头,背包中间的 \(O(n^4A)\) 做法。
我们可以继续注意力惊人的注意到左上和右下角一定是最小值和次小值,这样时间复杂度就骤减到 \(O(n^2V)\) 了。
#include<bits/stdc++.h>
using namespace std;
const int N=55,M=2500005;
int n,a[N],up[N],dn[N],sum,vs[N];
bitset<M>dp[N][N/2];
void dfs(int x,int num,int nm){if(num==2) return vs[num]=1,void();vs[num]=(dp[num-1][nm][x]==0);dfs(x-vs[num]*a[num],num-1,nm-vs[num]);
}signed main(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0),cin>>n;for(int i=1;i<=2*n;i++) cin>>a[i],sum+=a[i];sort(a+1,a+2*n+1),dp[2][0][0]=1,sum-=a[2]+a[1];for(int i=3;i<=2*n;i++) for(int k=1;k<=n;k++)dp[i][k]=dp[i-1][k]|(dp[i-1][k-1]<<a[i]);for(int j=sum/2,k=(sum+1)/2;;j++,k--){if(dp[n*2][n-1][j]==1){dfs(j,n*2,n-1);break;}if(dp[n*2][n-1][k]==1){dfs(k,n*2,n-1);break;}}for(int i=1,tp=0;i<=2*n;i++)vs[i]?up[++tp]=a[i]:dn[i-tp]=a[i];sort(up+1,up+n+1),sort(dn+1,dn+n+1);for(int i=1;i<=n;i++) cout<<up[i]<<" ";cout<<"\n";for(int i=n;i;i--) cout<<dn[i]<<" ";return 0;
}