Hamilton路径

NCSTOJ
FAQ
Problem Set
Status
Rank List
Contest/Task
蓝鲸’s MailBox
Wanna change your avatar? Read FAQ!
F : [算法竞赛进阶指南]Hamilton路径
Time Limit:2 Sec Memory Limit:128 MiB
Back Submit
Description
给定一张 n(n≤20) 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短Hamilton路径。 Hamilton路径的定义是从 0 到 n-1 不重不漏地经过每个点恰好一次。

扩展题目:POJ2288 Islands and Bridges

Input
第一行一个整数n。

接下来n行每行n个整数,其中第i行第j个整数表示点i到j的距离(一个不超过10^7的正整数,记为a[i,j])。

对于任意的x,y,z,数据保证 a[x,x]=0,a[x,y]=a[y,x] 并且 a[x,y]+a[y,z]>=a[x,z]。

Output
一个整数,表示最短Hamilton路径的长度
Sample Input
4
0 2 1 3
2 0 2 1
1 2 0 1
3 1 1 0
Sample Output
4

#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
using namespace std;
int f[1<<20][20];//每一行表示一种走的方法
int hamliton(int n,int weight[20][20])
{
	memset(f,0x3f,sizeof(f));//这里相当于赋最大值的意思因为20是占5位
	//所以至少要填满5位越多越好
	f[1][0]=0;//初始位置因为行要看成20位二进制所以1表示的是只有1走过的情况,而1到1的距离是0
for(int i=1;i<1<<n;i++)//通过二进制枚举走过的情况
	for(int j=0;j<n;j++)
		if(i>>j&1)//j位置走过了
			for(int k=0;k<n;k++)
				if((i^1<<j)>>k&1)//k位置也走过了
					//当在i状态下j位置和k位置都走过时进行如下判断
					//更新i状态下j位置的最短路径
					//它是由没走在原来i状态的情况下往前考虑一步
					//即没走j时,即(i^1<<j)因为有上一步的判断所以这一句表示的是
					//将j位清零,即达到了退一步的目的
					//然后依次循环在(i^1<<j)的情况下k位的最短路径,因为将原来二进制某一位
					//清零后一定是变小了,那么它一定在之前寻找到了最短路径
					//在由k位置的最短路径加上k位置到j位置的距离
					//在经过最下判断则得到由没走j位置的(i^1<<j)状态
					//更新到i状态的j的最短路径
					f[i][j]=min(f[i][j],f[i^1<<j][k]+weight[k][j]);
				//最后在全经过的状态下即n位二进制全1,即为1<<n-1状态
				//最后一位n-1的最短路径

				return f[(1<<n)-1][n-1];

} 
int main(){
	//freopen("qwe.txt","r",stdin);
	int n;
	int w[20][20];
	cin>>n;
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			cin>>w[i][j];
		cout<<hamliton(n,w);
return 0;

}

猜你喜欢

转载自blog.csdn.net/qq_42635159/article/details/89172183