`
evasiu
  • 浏览: 169474 次
  • 性别: Icon_minigender_2
  • 来自: 广州
博客专栏
Fa47b089-e026-399c-b770-017349f619d5
TCP/IP详解卷一>阅读...
浏览量:12549
社区版块
存档分类
最新评论

图论--旅行商问题

阅读更多

五一果然基本献给了数据压缩(除了两个晚上用于打球),看了小波的一些理论,看了EZW编码和SPIHT编码方法,看了一篇基于提升小波和改进SPIHT算法的图像编码的论文,最后就决定以这篇文章为基础进行实现了。还好理解了SPIHT算法的整个过程了,不然这篇文章估计也看不懂。现在比较愁的是,我要用matlab实现好呢?还是用c实现啊?matlab不是很熟,可是如果c的话可能要有很多跟图像相关的操作,还有矩阵。。。有关数据压缩的,就先到这里一个段落吧。

 

最后一个晚上开始做旅行商问题(tsp)。

 

首先描述一下问题:salesman从某个城市出发,要去很多城市推销商品,从a城市到b城市路上的开销已知,现在要找一条路,从salesman从该城市出发,最后又回到这个城市,路上的开销最少。

 

以前一直听说tsp是一个NP难问题,做数模的时候从来不敢轻易用精确算法来解决这个问题(其实当时图的规模也不大),对于很多启发式算法又其实不是很懂,总之就是,我从来没有觉得答案是最优解。借着这次机会,消除了一些思维误区,也告诫自己,凡事不能浅尝辄止。

 

解题思路是从《图论与代数结构》这本书上看来的,我结合例子试着复述一遍:

 

例:G=[ 0 42 33 52 29

            42  0 26 38 49

            33 26  0 34 27

            52 38 34  0 35

            29 49 27 35  0 ]

假设以顶点1、2为顶点的边表示为e12

 

首先是对边根据它的权重从小到大排序。

e23(26)  e35(27)  e15(29)  e13(33)  e34(34)  e45(35)  e24(38)  e12(42)  e25(49)  e14(52)

 

构造哈密顿回路H:

把符合条件的边一条一条地加到H中去(符合条件指的是:如果将某条边加入到H中去,不会有顶点的入度超过3)直到H有n条边。这样就构成了一个哈密顿回路。

应该说,构成哈密顿回路的过程是一个搜索过程。搜索的树的形状差不多是这样子的:

根节点是人为构造的,设它为level=-1, 下面包含了(n-1)*n/2-n+1个子节点,如上面的例子,n=5,根节点下面有6个子节点,分别是

e23 e35 e15 e13 e34 e45

它代表的含义是,可以把这条边放在第0层,并接着往下再搜索4条边形成一个H回路。这也就是为什么只有(n-1)*n/2-n+1个子结点了。

以e23为结点的树的第1层有孩子结点:e35 e15 e13 e34 e45 e24

以e35为结点的树的第1层有孩子结点:e15 e13 e34 e45 e24

看出来没有,子结点的边一定比父结点要大。

深搜的时候,有两个条件可以进行剪枝:

(1)如果边不符合条件,以这条边根结点的树不需要再往下搜索

(2)如果通过该边得到的回路的总开销大于前面找到的回路的总开销,以这条边的父结点为根结点的树不再往下搜索

第一点是很显然的,比方说从e23这条边进行深搜,路径是:e23->e35->e15,e15下面有子结点:e13, e34, e45, e24, e12, e12、e34、e45都不符合要求,因此这些树都不需要进行搜索了。

第二点需要想到的是,父结点下面的siblings是从左到边变大的,且子结点都比父结点大,所以如果左边的搜索到的H回路已经比原先的H回路权重大了,再往下或往右搜索肯定是更大的,所以整个父结点都不需要搜索了。

 

不知道我把问题解释清楚了没有?

 

其实之前看书里的解题思路的时候,我还不是这么想的,在实现的过程中递归到我自己也迷糊了,最后才提炼出来这样的结果的,呵呵。我还是不大会递归啊。

 

最后看一下实现的代码:

 

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

double currentMax = 0.0;
int maxRound;

//a struct to ease index
typedef struct {
	int start;
	int end;
	double cost;
	int index;
}edge;

//record the optimum route
edge* bestPath;

//the function for qsort
int edgeCompare( const edge* a, const edge* b ){
	if( a->cost - b->cost > 0.0001 )
		return 1;
	if( a->cost - b->cost < 0.0001 )
		return -1;
	return 0;
}

double tsp( edge* cost, edge* stack, int* count, int n, double current, int level ){
	int i;
	if( level == n-1 ){
		if( current < currentMax ){
			currentMax = current;
			for( i=0; i<n; i++ )
				bestPath[i] = stack[i];
			}
		return currentMax;
	}
	for( i=stack[level].index+1; i<n*(n-3)/2+level+2; i++ ){
		//if the edge is unproper, no further tsp is performed to this node
		if( count[cost[i].start]+1 < 3 && count[cost[i].end]+1 < 3 ){
			stack[level+1] = cost[i];
			count[cost[i].start] ++;
			count[cost[i].end]++;
			current += cost[i].cost;
			double r;
			//if the cost of the H route newly get is no better then the previously best one
			//no further tsp is performed to this level, that's this node's father node
			if(  (r = tsp( cost, stack, count, n, current, level+1 )) > currentMax )
				return currentMax;	
			//restore after recursive call
			count[cost[i].start]--;
			count[cost[i].end]--;
			current -= cost[i].cost;
		}
	}
	return currentMax;
}

main(){
	int num, s, e, i;
	double c;
	edge* edges;
	//the graph is construct by user input
	printf( "enter the number of nodes: " );
	scanf( "%d", &num );
	maxRound = num;
	bestPath = (edge*)malloc( sizeof(edge)*num );
	edges = (edge*)malloc( sizeof(edge)*num*(num-1)/2 );
	printf( "enter the edge and its cost in such a triple: <start end cost>\n" );
	i=0;
	while( i<num*(num-1)/2 ){
		scanf( "%d %d %lf", &s, &e, &c );
		edges[i].start = s;
		edges[i].end = e;
		edges[i].cost = c;
		currentMax += c;
		i++;
	}
	qsort( edges, num*(num-1)/2, sizeof(edge), edgeCompare );
	for( i=0; i<num*(num-1)/2; i++ )
		edges[i].index = i;
	
	int* count = (int*)malloc( sizeof(int)*(num+1) );
	memset( count, 0, sizeof(int)*(num+1) );
	edge* stack = (edge*)malloc(sizeof(edge)*num );
	double r;
	//level -1
	for( i=0; i<num*(num-1)/2-num+1; i++ ){
		stack[0] = edges[i];
		count[stack[0].start]++;
		count[stack[0].end]++;
		if( (r=tsp( edges, stack, count, num, edges[i].cost, 0 ))>currentMax )
			break;
		}
	printf( "haha, let's make a test... total: %.1lf\n", currentMax );
	for( i=0; i<num; i++ )
		printf( "%d %d %lf\n", bestPath[i].start, bestPath[i].end, bestPath[i].cost );
}

 

分享到:
评论

相关推荐

    哈尔滨工业大学图论-总结-CSDN下载

    3. 旅行商问题:经典的图论问题,目标是最小化旅行商访问所有城市的总距离。 压缩包中的“哈尔滨工业大学图论-总结.pdf”很可能会涵盖以上这些内容,并可能包含更多的高级主题,如哈密顿回路、平面图、图的染色问题...

    数学建模-图论-总结.zip

    7. **旅行商问题**: 找出访问多个城市并返回起点的最短路线,是著名的NP完全问题。 通过深入学习和理解图论,我们可以运用这些理论工具解决实际问题,提高问题解决的效率和准确性。这份“数学建模-图论-总结.ppt”...

    图论- 环与块- 最小环.rar

    找到最小环对于理解和优化某些问题非常有用,比如在旅行商问题中,寻找最短的访问所有城市并返回起点的路径,最小环的信息可以帮助我们设定初始的解决方案。在有向图中,最小环的定义可能会有所不同,因为边的方向...

    图论- 图的遍历- 哈密顿问题.rar

    哈密顿问题的一个实际应用是旅行商问题,其中旅行商试图找出访问多个城市并返回原点的最短路线,每个城市代表图中的一个顶点,边的长度表示两个城市之间的距离。 解决哈密顿问题的传统方法包括回溯法、动态规划和...

    旅行商问题-A算法-java

    综上所述,"旅行商问题-A算法-java"这个主题涵盖了图论、搜索算法、启发式函数设计、数据结构使用(如优先队列和集合)、路径回溯、性能优化和错误处理等多方面的计算机科学知识。在Java环境中实现这个算法,不仅...

    图论- 最短路- Floyd 算法.rar

    - 旅行商问题:作为求解TSP问题的预处理步骤,找到各个城市之间的最短路径。 **总结** Floyd-Warshall算法是解决图论中找到所有节点对最短路径的有效工具。其核心在于通过迭代所有可能的中间节点来不断优化路径。...

    旅行商问题-遗传算法--java

    旅行商问题(Traveling Salesman Problem,TSP)是一个经典的组合优化问题,它涉及寻找最短的可能路线,使得旅行商能够访问每个城市一次并返回起点。这个问题在计算机科学、运筹学和图论中都有广泛的研究,因为它...

    MATLAB数学建模算法 图论 第5章 旅行商问题 共9页.pptx

    MATLAB数学建模算法 图论 第5章 旅行商问题 共9页.pptx

    旅行商问题 C语言解法

    旅行商问题(Traveling Salesman Problem,TSP)是一个经典的组合优化问题,它在图论领域内占有重要地位。该问题描述如下:一个旅行商需要访问n个城市,并且每个城市只访问一次,最后返回起点,目标是使得旅行的总...

    TSP_MATLAB-master_旅行商问题_matlab_tsp_

    旅行商问题(Traveling Salesman Problem,简称TSP)是一个经典的组合优化问题,在数学、计算机科学和运筹学领域有着广泛的研究。这个问题的基本设定是:一个旅行商需要访问n个城市,每个城市只访问一次,然后返回...

    电子科大研究生图论05-14年图论期末试题.pdf

    - 旅行商问题(traveling salesman problem, TSP) 由于提供的文档内容并不完整,无法给出具体的题目分析。但是,根据文件标题和描述,这些期末试题很可能包含了上述图论的相关问题和概念。通过这些试题,学生可以...

    matlab-TSP(旅行商问题).rar

    《旅行商问题与MATLAB实现详解》 旅行商问题(Traveling Salesman Problem,简称TSP)是运筹学中的一个经典问题,属于组合优化领域。这个问题的基本设定是:一个销售员需要访问n个城市,每次只能访问一个城市,并且...

    LINGO - 最优连线问题与旅行商问题

    旅行商问题 最优连线问题也是最小生成树问题(Minimum Spaning Tree Problem)是求网络中长度最小的生成树, 旅行商问题(Traveling Salesman Problem)也称货郎担问题,是求最优的Hamilton圈 (Hamiltonian Cycle). 这...

    旅行商问题 实验报告+代码

    旅行商问题(Traveling Salesman Problem,简称TSP)是一个著名的组合优化问题,在计算机科学和运筹学领域具有重要地位。这个问题的设定是这样的:一个旅行商需要访问n个城市,每个城市只访问一次,最后返回起点,...

    旅行商问题求解(C++)

    旅行商问题(Traveling Salesman Problem,TSP)是一个经典的组合优化问题,它在图论和运筹学中占有重要地位。这个问题描述了一个旅行商如何有效地访问一系列城市,每个城市只访问一次,最后返回起点,使得总行程...

    旅行商问题可行性研究

    旅行商问题(Traveling Salesman Problem,简称TSP)是组合优化领域中的一个经典难题,具有广泛的应用背景,涉及到计算复杂性理论、图论、运筹学等多个学科。旅行商问题最早在20世纪20年代由数学家兼经济学家卡尔·...

    TensorFlow实现霍普菲尔德网络(Hopfield)解决城市旅行商问题(TSP)

    用用图论的术语来说,旅行商问题就是在赋权完全图上找一个权最小的 Hamilton 圈。但是,首先从应用上来说,很多实际应用问题,如印制电路板的、连锁店的货物配送路线等,经简化的处理后,均可转化为旅行商问题TSP。

    旅行商问题matlab程序

    旅行商问题(Traveling Salesman Problem,TSP)是一个经典的组合优化问题,它在图论、运筹学和计算机科学领域都有广泛的研究。该问题的基本情境是:一个旅行商需要访问n个城市,每个城市只访问一次,并且最后返回...

    旅行商问题-使用自组织映射SOM解决旅行商问题-题解.zip

    旅行商问题(Traveling Salesman Problem,TSP)是一个经典的组合优化问题,它在图论和运筹学中占有重要地位。这个问题描述了一个旅行商如何有效地访问一系列城市,每个城市只访问一次,最后返回起点,使得总行程...

Global site tag (gtag.js) - Google Analytics