站外题求调
找不到题解啊。。
给出一个完全的有向图,求一条除起点外(最终回到起点)经过且仅经过每个顶点一次的路径,使得经过的权值最大。
3
0 10 30
30 0 30
50 30 0
90
1
2
3
1
n≤15
思路都在代码里了:
#include<bits/stdc++.h>
//#define int long long
using namespace std;
int ans,ans2,n,a[16][16],f[16][1<<16][16]/*起点,状态,终点*/,lu[16][1<<16][16][16]/*起点,状态,终点,第几个访问到*/,cnt[16][1<<16][16]/*一样*/,Maxl,Maxr;
signed main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%d",&a[i][j]),/*初始化*/f[i][(1<<(i-1))|(1<<(j-1))][j]=a[i][j],/*记录一开始两个点路径*/lu[i][(1<<(i-1))|(1<<(j-1))][j][++cnt[i][(1<<(i-1))|(1<<(j-1))][j]]=i,lu[i][(1<<(i-1))|(1<<(j-1))][j][++cnt[i][(1<<(i-1))|(1<<(j-1))][j]]=j;
for(int ST=0;ST<=(1<<n)-1;ST++)for(int i=1;i<=n;i++)
if(ST&(1<<(i-1)))/*利用已访问过的一个点*/for(int j=1;j<=n;j++){
if(ST&(1<<(j-1)))/*更新未访问过的一个点*/continue;
for(int k=1;k<=n;k++)/*枚举起点*/if((ST&(1<<(k-1))/*起点当然要被访问过的*/)&&f[k][ST][i]+a[i][j]>f[k][ST|(1<<(j-1))][j])f[k][ST|(1<<(j-1))][j]=f[k][ST][i]+a[i][j],lu[k][ST|(1<<(j-1))][j][++cnt[k][ST|(1<<(j-1))][j]]=j;/*更新答案、路径*/}
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(i!=j)if(ans<f[i][(1<<n)-1][j]+a[i][j]/*+a[i][j]是还要访问回去*/)ans=f[i][(1<<n)-1][j]+a[i][j],Maxl=i,Maxr=j;
printf("%d\n",ans);
for(int i=1;i<=n;i++)printf("%d\n",lu[Maxl][(1<<n)-1][Maxr][i]);
printf("%d\n",Maxl);
return 0;}