看我看我
  • 板块学术版
  • 楼主xs_siqi
  • 当前回复6
  • 已保存回复6
  • 发布时间2023/2/2 15:03
  • 上次更新2023/10/24 02:03:33
查看原帖
看我看我
401088
xs_siqi楼主2023/2/2 15:03

站外题求调

找不到题解啊。。

给出一个完全的有向图,求一条除起点外(最终回到起点)经过且仅经过每个顶点一次的路径,使得经过的权值最大。

3
0 10 30
30 0 30
50 30 0
90
1
2
3
1

n15n\leq 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;}
2023/2/2 15:03
加载中...