最短Hamilton路径
Posted KylinLzw (●—●)
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最短Hamilton路径相关的知识,希望对你有一定的参考价值。
最短Hamilton路径
二进制状态压缩的应用
Hamilton路径的定义是从0到n-1不重不漏地经过每个点一次。
思路:
我们可以采用一个n位的二进制数,用其第i(0<=i< n)为1表示第i个点已经被经过,0表示还没被经过,这样我们可以使用f[i,j] (0<=i<2^n,0<=j< n)表示二进制i时,且目前处于j点的最短路径,这样n位全是1的状态代表的是经过所有点的最短路状态。
1.初始化:先把f数组初始化成正无穷,f[1,0]=0表示在起点0,最短路径也是0。
2.转移方程:f[i,j]=min(f[i xor (1<< j),k]+weight(k,j)),其中0<=k< n并且(i>>j)&1=1。(解释:当前的j点必须是第一次经过并且只能是经过一次,所以转移而来的状态必须是j点还没经过,但是目前的i位置则是j已经经过的状态,也就是i xor (1<< j)。另外,上一时刻的位置是任意一个是1的数位k,从k走到j需要经过的路程为weight(k,j)取最小值。
3.最终状态:f[(1<<n)-1,n-1]表示经过所有的点并且位于n-1的位置。
int Hamilton()
//初始化
memset(f,0x3f,sizeof f);
f[1][0]=0;
//枚举每个状态和转移的状态
for(int i=1;i<(1<<n);i++)
for(int j=0;j<n;j++)
if(i>>j&1)
for(int k=0;k<n;k++)
if((i-(1<<j))>>k&1)f[i][j]=min(f[i-(1<<j)][k]+weight[k][j],f[i][j]);
//返回答案
return f[(1<<n)-1][n-1];
模板题:
ACWing 91. 最短Hamilton路径
传送门
#include<iostream>
#include<cstring>
using namespace std;
const int N=1<<21,M=21;
int weight[22][22],f[N][M];
int n;
void Hamilton()
memset(f,0x3f,sizeof f);
f[1][0]=0;
for(int i=1;i<(1<<n);i++)
for(int j=0;j<n;j++)
if(i>>j&1)
for(int k=0;k<n;k++)
if((i-(1<<j))>>k&1)f[i][j]=min(f[i-(1<<j)][k]+weight[k][j],f[i][j]);
int main()
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)cin>>weight[i][j];
Hamilton();
cout<<f[(1<<n)-1][n-1]<<endl;
以上是关于最短Hamilton路径的主要内容,如果未能解决你的问题,请参考以下文章