标签:展示 有一个 pre false main include std 压缩 表示
最短Hamilton路径
给定一张 nn 个点的带权无向图,点从 0~n?10~n?1 标号,求起点 00 到终点 n?1n?1 的最短 Hamilton 路径。
Hamilton 路径的定义是从 0,0 到 n?1,n?1 不重不漏地经过每个点恰好一次。
第一行输入整数 nn。
接下来 n,n 行每行 n,n 个整数,其中第 ii 行第 jj 个整数表示点 ii 到 jj 的距离(记为 a[i,j]a[i,j])。
对于任意的 x,y,zx,y,z,数据保证 a[x,x]=0,a[x,y]=a[y,x]a[x,x]=0,a[x,y]=a[y,x] 并且 a[x,y]+a[y,z]≥a[x,z]a[x,y]+a[y,z]≥a[x,z]。
输出一个整数,表示最短 Hamilton 路径的长度。
1≤n≤20
0≤a[i,j]≤1e7
5
0 2 4 5 1
2 0 6 5 3
4 6 0 8 3
5 5 8 0 5
1 3 3 5 0
18
分析:
他的题意是不重不漏的经过每一个点求出他的最短路径,假如只有4个点0,1,2,3 , 那么0 -> 1 -> 2 -> 3 和 0 -> 2 -> 1 -> 3 是属于从1号点到3号点的两个不同走法,但是他俩只有一个最小
值,他俩路径有一个共同点就是起点和终点一样,所以咱们可以把状态压缩成f[state][j],这个数组的含义是状态state终点是j的集合的路径最小值,状态转移的话,可以进行如下状态转移 ->
f[state][j] = min(f[state - (1<<j)][k] + weight[k][j],f[state][j]),这是代码的实现,下面讲一下思路,就是找一个没有j的状态state_k,然后加上k到j的距离,下面展示一下代码:
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 const int N = 25,M = (1<<20)+10; 5 int f[M][N],weight[N][N]; 6 int main(){ 7 int n; 8 cin>>n; 9 for(int i=0;i<n;i++) 10 for(int j=0;j<n;j++) 11 cin>>weight[i][j]; 12 memset(f,0x3f,sizeof f); 13 f[1][0] = 0; 14 for(int i=0;i < 1<<20 ;i++) 15 for(int j=0;j<n;j++) 16 if(i>>j & 1){ 17 for(int k=0;k<n;k++) 18 if(i - (1<<j) >> k & 1)//这个地方判断k有没有确实特别的精妙 19 f[i][j] = min(f[i][j],f[i-(1<<j)][k] + weight[k][j]); 20 } 21 cout<<f[(1<<n)-1][n-1]<<endl; 22 return 0; 23 }
标签:展示 有一个 pre false main include std 压缩 表示
原文地址:https://www.cnblogs.com/QDUshy/p/14639149.html