完成状态的最优值,数据范围<=16优先考虑状态压缩。
枚举每个起点,从这个点开始求总路径,难点就在记录路径的长度。,如果经过一个转移点,路径长度+1,其他的点没有经过,保持原来的值。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
using namespace std;
const int maxn=17,inf=0x3f3f3f3f;
int map[maxn][maxn],step[maxn][maxn],num,n,m,nums;
int f[1<<16],cs[maxn][1<<16];
int dp(int s){
memset(f,0x3f,sizeof(f));
nums=(1<<n)-1;
f[1<<(s-1)]=0; cs[s][(1<<(s-1))]=0;
for(int i=0;i<=nums;i++)//枚举所有可能的状态;
for(int j=1;j<=n;j++)
if(i&(1<<(j-1))) //枚举当前状态下到了第j个结点
for(int k=1;k<=n;k++) {//从j之k,找出到k的最优值。
if((i&(1<<(k-1)))==0&&map[j][k]<inf){ //如果第k结点还到,那么到达k,并更新其值。
int p=1<<(k-1);
int x=f[i]+(cs[j][i]+1)*map[j][k];
if(f[i|p]>x){
f[i|p]=x;
for(int l=1;l<=n;l++)cs[l][i|p]=cs[l][i];//原来的没经过j到
cs[k][i|p]=cs[j][i]+1;//k点经过j点到达,步数增加
}
}
}
return f[nums];
}
int main(){
memset(map,63,sizeof(map));
cin>>n>>m;
int u,v,x;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&x);
map[u][v]=min(map[u][v],x);
map[v][u]=map[u][v];
}
int ans=0x3f3f3f3f;
for(int i=1;i<=n;i++)
ans=min(ans,dp(i));
cout<<ans<<endl;
return 0;
}