哈密顿回路与旅行商问题的求解

【算法设计】 专栏收录该内容
9 篇文章 0 订阅

哈密顿图:图G的一个回路,若它通过图的每一个节点一次,且仅一次,就是哈密顿回路.存在哈密顿回路的图就是哈密顿图.哈密顿图就是从一点出发,经过所有的必须且只能一次,最终回到起点的路径.图中有的边可以不经过,但是不会有边被经过两次.

哈密顿回路之中的图并不要求是完全图,而当这个图的完全图也就是每个顶点之间都存在路径,并且是加权图的时候,哈密顿回路的问题就演变成了旅行商问题,因此上述两个问题的求解方法十分相似。

首先来求哈密顿回路问题

1.我们很容易想到用蛮力法,即对于给定的无向图(V,E) 依次考察图中所有顶点的全排列,而当满足相邻顶点之间存在边并且最后一个顶点与第一个顶点之间也存在边时就符合条件。

2.采用dfs,并且适当减枝。 下面我们采用这种方法求解

input:

5
0 1 1 1 0
1 0 1 0 1
0 1 0 1 1
1 0 1 0 1
0 1 1 1 0

 

//哈密顿回路问题
#include<stdio.h>
int x[100];
int visit[100];
int arc[6	][6];
int n;
void dfs(int step)
{
	int i,j;
	if(step==n&&arc[x[step-1]][0]==1) //最后一步到达的顶点与起点之间存在路径 
	{
		printf("路径:");
		for(i=0;i<n;i++)
			printf("%d ",x[i]+1);
		printf("\n");
			return ;
			
	}
	else
	{
		for(j=0;j<n;j++)
		{
			if(visit[j]==0&&arc[x[step-1]][j]==1) //j未访问并且当前顶点与j顶点之间存在路径 
			{
				visit[j]=1;
				x[step]=j;	//下一个访问的顶点为j 
				dfs(step+1);
				visit[j]=0;
				x[step]=0;			
			}
			
		}
	}
	
} 
int main(void)
{
	int i,j;
	scanf("%d",&n);
 	for(i=0;i<n;i++)
		for(j=0;j<n;j++)
			scanf("%d",&arc[i][j]);
	visit[0]=1;  //起点置为已经访问
	x[0]=0;
	dfs(1);
	return 0;
	
}

 

旅行商问题的求解 :有若干个城市,任何两个城市之间的距离都是确定的,现要求一旅行商从某城市出发必须经过每一个城市且只在一个城市逗留一次,最后回到出发的城市,问如何事先确定一条最短的线路已保证其旅行的费用最少?

旅行商问题与哈密顿回路问题十分相似,都是经过每一个顶点一次最后回到出发的城市,不同的是旅行商问题对应的是完全图,即每个顶点之间都存在路径,并且路径长度已知。

 

input:

4
0 2 5 7
2 0 8 3
5 8 0 1
7 3 1 0
output:

11

//旅行商问题,对应完全图
//哈密顿回路问题 对应非完全图 
#include<stdio.h>
int x[100];
int visit[100];
int arc[6][6];
int n,count,bestCount=9999999;
void dfs(int step,int count)
{
	int i,j;	 
	if(bestCount<count) //减枝,当然所经过的路径长度大于最小长度 
		return;
	if(step==n) //已经走过n个顶点 
	{
	 
		count+=arc[x[step-1]][0];
		bestCount=count;	 
		return ;
			
	}
	else
	{
		for(j=0;j<n;j++)
		{
			if(visit[j]==0) //j未访问
			{
				visit[j]=1;//置为已经访问 
				x[step]=j;	//访问该顶点 
				dfs(step+1,count+arc[x[step-1]][j]); 
				visit[j]=0;
				x[step]=0;			
			}
			
		}
	}
	
} 
int main(void)
{
	int i,j;
	scanf("%d",&n);
 	for(i=0;i<n;i++)
		for(j=0;j<n;j++)
			scanf("%d",&arc[i][j]);
	visit[0]=1;
	x[0]=0;
	dfs(1,0);
	printf("%d ",bestCount);	
	return 0;
	
}

 

  • 2
    点赞
  • 0
    评论
  • 18
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值