给定一张 个点的带权无向图,点从 标号,求起点 到终点 的最短 Hamilton 路径。
Hamilton 路径的定义是从 到 不重不漏地经过每个点恰好一次。
xxxxxxxxxx
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
其中代表一共有个点,下面的矩阵中代表点到点的路径。
xxxxxxxxxx
18
输出就直接输出答案即可。
首先用一个数来表示当前状态,数字二进制下的第位表示点是否经过过(1表示已经经过过了)。
然后用一个数组表示终点位于点且路径状态位的最短总路径。
其中合法的必须满足的第位是(因为终点在表面点经过过),即为真。
的值为所有能一步到达的点中,的最小值。
初始值:起点是,这时候只经过了点,所以只有最低为是其他位都是,初始值就是。又因为到的距离是,所以初始值。
需要注意-
的优先级大于>>
这里可以先参考一下后面的完整代码
memset(f, 0x3f, sizeof(f))
赋初值为“无穷大”xxxxxxxxxx
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
cin>>A[i][j];
输入每两点之间的距离
f[1][0]=0
初始化起点自身的状态xxxxxxxxxx
for(int i=0;i<1<<n;i++) // 先枚举每种状态i
for(int j=0;j<n;j++) // 再枚举这种状态下的终点j
if(i>>j&1) // 这种状态的第j位必须是1才有意义
for(int k=0;k<n;k++) // 最后枚举这种到点j的上一个点k
if((i-(1<<j))>>k&1) // (i-(1<<j))是上一种状态,它的第k位必须是1
f[i][j]=min(f[i][j], f[i-(1<<j)][k]+A[k][j]); // 取所有能到达这一点的选项中的最小值
cout<<f[(1<<n)-1][n-1]<<endl
输出最终结果:状态是起点到终点的每个点都经过,终点是n-1。