回溯法求解TSP问题(旅行商问题)

定义:旅行商问题,即TSP问题(Traveling Salesman Problem)又译为旅行推销员问题、货郎担问题,是数学领域中著名问题之一。假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求得的路径路程为所有路径之中的最小值。


本提中对TSP问题,可以看作全排列问题,只不过在排列过程中,只对符合条件的数进行,那怎末判断要去的下一个城市(下一个数是否满足要求,这里就采用了限界(代价)函数,用来减少不必要的循环,也就是所谓的剪枝函数的作用)

这里的限界函数用的是屈婉玲老师的算法与设计分析中提到的方法,
回溯法求解TSP问题(旅行商问题)_第1张图片
回溯法求解TSP问题(旅行商问题)_第2张图片

代码如下:

#include 
#define max 100
int num ;
int g[max][max], x[max], bestx[max]; //best[]是用来存储最终的最短路径 
int cl=0;
int best = max;

//交换函数 
void swap(int &a, int &b)
{
	int tem = a;
	a= b;
	b =tem;
}


//界定函数,按照屈婉玲老师的算法公开课视频讲解的给出的实现,
//下界公式为 min{cl + min1 + temmin}解释一下就是当前走过的路径+下一个要找的最短路径+剩下点的到其他点的最短路径(最后这个temmin是用贪心的思想求剩下没走过城市的最路径)
//当然,贪心毕竟不是从整体最优考虑,而是从局部最优考虑,所以,在后来的寻找中,如果找到比 cl + min1 + temmin求解出来的最短路径,则可以考虑往下找,否则剪枝。 
int  bound( int t)
{
	int min1=max ,min2=max, temmin=0;  //这里min与min2初始化一下 
	for(int i=t; i<=num; i++)
	{
		//这里求min1 
		if( g[x[t-1]][x[i]] != -1 && g[x[t-1]][x[i]]  < min1)
		{
			min1 =g[x[t-1]][x[i]]; //这里求要去的第t城市。选择当前到t路径最短的 
		}
		
		//这里求min2 
		for(int j =1; j<=num; j++) //贪心的思想,求剩下的路径的下界 
	     {
	     	if( g[x[i]][x[j]]!=-1 &&  g[x[i]][x[j]]!=0  && g[x[i]][x[j]] < min2)
	     	{
	     		min2 = g[x[i]][x[j]];
			 }
		 }
		 temmin += min2; //这里是剩下点的最短出出路径的和的累加 
	}
	return cl+ min1 + temmin;
}

//这里选择城市的方式类似于全排列问题,只不过这里加了 一个判断条件就是t与之前的城市t-1有路径,这里是有选择性的选择点(这里也叫剪枝)。 
void prim(int t)
{
	//如果到叶节点,则表示所有城市都走过了,这个时候就保存一下最短路径以及相应的城市顺序 ,当然是满足条件就是比之前的bext还要小的路径的长度,每次取最优 
	if(t>num )
	{
		if(g[x[num]][1]!=-1 &&  cl + g[x[num]][1]  ", bestx[i]);
	 }
	 
	 if(g[x[num]][1]!=-1);
	 {
	 	printf("%d",bestx[1]); 
	 }
	 
	 printf("\n"); 
	 printf("\n最短路径为:  %d", best); 
	 return 0;
 } 

程序运行如下:

回溯法求解TSP问题(旅行商问题)_第3张图片
回溯法求解TSP问题(旅行商问题)_第4张图片

你可能感兴趣的:(初阶算法,算法,c语言)