文章目录

  • 一、TSP 概述
    • 1. TSP
    • 2. 数学模型
    • 3. TSP分类
  • 二、贪心算法
    • 1. 算法思路
    • 2. 算法框架
    • 3. 问题
  • 三、贪心算法求解 TSP

一、TSP 概述

1. TSP

旅行商问题即 TSP(Traveling Salesman Problem),又称为货郎担问题,是数学领域中著名问题之一。假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求得的路径路程为所有路径之中的最小值。
TSP问题是一个组合优化问题,该问题可以被证明具有NPC计算复杂性。从图论的角度来看,该问题实质是给定一个带权完全无向图(顶点表示城市,边表示道路,权重是道路的成本或距离),找一个权值最小的 Hamilton 回路。

2. 数学模型

记 G = (V, E) 为赋权图,V = {1, 2 , ……,n} 为顶点集,E 为边集,各顶点间距离为 Cij,已知(Cij > 0,Cij = +∞,i,j ∈ V),并设
xij={1,边(i,j)在最优路线上0,其他x~ij~= \begin{cases} 1,边(i, j)在最优路线上 \\ 0,其他 \end{cases}x ij ={1,边(i,j)在最优路线上0,其他​
则旅行商问题的数学模型可写成如下的线性规划形式:
p=∑i≠jcijxijp = \sum_{i ≠ j} c_{ij}x_{ij}p=i​=j∑​cij​xij​
s.t.={∑j≠icij=1,i∈V∑i≠jcij=1,j∈V∑i,j∈Sxij≤∣K∣−1,K⊂Vxij∈{0,1}i,j∈Vs.t.=\begin{cases} \sum_{j ≠ i} c_{ij} = 1 ,& i∈V \\ \sum_{i ≠ j} c_{ij} = 1 ,& j∈V \\ \sum_{i,j∈S} x_{ij} ≤|K|-1 ,& K ⊂V \\ x_{ij}∈\{0, 1\} & i,j∈V\\ \end{cases}s.t.=⎩⎪⎪⎪⎨⎪⎪⎪⎧​∑j​=i​cij​=1,∑i​=j​cij​=1,∑i,j∈S​xij​≤∣K∣−1,xij​∈{0,1}​i∈Vj∈VK⊂Vi,j∈V​
K 为 V 的所有非空子集,|K| 为集合 K 中所含图 G 的顶点个数。前两个余数意味着对每个顶点而言,出度和入度都为1,后一约束则保证没有任何子回路解的产生,于是满足上述约束的解构成了一条 Hamilton 回路。

3. TSP分类

旅行商问题按把不同的分类方法可以分为不同的种类,这里只介绍距离矩阵划分: 当 cij = cji,(i, j ∈ V)时,问题被称为对称型旅行商问题,反之称为非对称型旅行商问题,非对称旅行商问题可以化为对称型旅行商问题,用对称型的方法求解。当对所有的 i, j, k ∈[1, n],有不等式 cij + cjk ≥ cik,问题满足三角形不等式的,也称三角型旅行商问题。
旅行售货商问题(TSP)是组合优化领域的经典问题之一,而其中考虑多个旅行商的多旅行商问题(MTSP)是经典的旅行商问题的扩展,多种扩展形式1如下:

  1. 最小哈密顿链的问题:起点和终点不同;
  2. 非对称旅行商问题(asymmetric TSP):距离矩阵非对称的旅行商问题;
  3. 多人旅行商问题(muti-person TSP):由多人完成旅行的旅行商问题;
  4. 多目标旅行商问题(multi-objective TSP);
  5. 依次排序问题(Sequence ordering problem ,SOP):这类问题是非对称旅行商问题,在给定一系列顶点和距离矩阵下,寻找最短从顶点 1 到顶点 n 哈密顿链,同时满足限制:某些顶点要在一些顶点之前被连接。
  6. 载货量受限制的车辆路径问题(Capacitated vehicle routing problem,CVRP):给定 n-1 个顶点和一个仓库,一直顶点和顶点、仓库和顶点的距离,卡车载货量受限制,卡车每次在部分顶点和仓库之间往返,寻求一条经过所有顶点的最短路线。

二、贪心算法

贪心算法,又名贪婪算法,是一种常用的求解最优化问题的简单、迅速的算法。贪心算法总是做出在当前看来最好的选择,它所做的每一个在当前状态下某种意义上是最好的选择即贪心选择,并希望通过每次所作的贪心选择导致最终得到问题最优解。必须注意的是,贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态有关。

1. 算法思路

贪心算法以当前情况为基础根据某个优化测度作最优选择,而不考虑各种可能的整体情况,省去了为找最优解要穷尽所有可能而必须耗费的大量时间。贪心算法采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择,就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解。虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪心算法不要回溯。

贪心算法求解具有以下性质2

  1. 贪心选择性质:一个问题的整体最优解可通过一系列局部的最优解的选择达到,并且每次的选择可以依赖以前作出的选择,但不依赖于后面要作出的选择。这就是贪心选择性质。对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解
  2. 最优子结构性质:当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用贪心法求解的关键所在。

2. 算法框架

贪心算法没有固定的算法框架,算法设计的关键是贪心策略的选择,而贪心策略适用的前提是:局部最优策略能导致产生全局最优解。

//问题随机初始解
while(能向总目标前进一步)
{//利用可行的决策,从候选集合中求出可行解的一个解元素;
}

3. 问题

贪心算法也存在如下问题3

  • 不能保证求得的最后解是最佳的;
  • 不能用来求最大最小解问题;
  • 只能在某些特定条件约束的情况下使用,例如贪心策略必须具备无后效性等。

三、贪心算法求解 TSP

贪心策略基本思路:从一节点出发遍历所有能到达的下一节点,选择距离最近的节点作为下一节点,然后把当前节点标记已走过,下一节点作为当前节点,重复贪心策略,以此类推直至所有节点都标记为已走节点结束。
TSP 数据集来自于 TSPLIB 上的 att48.tsp,这是一个对称 TSP 问题,城市规模为48,其最优值为10628。其距离计算方法如下:

The edge weight type ATT corresponds to a special “pseudo-Euclidean” distance function. Let x[ i ] and y[ i ] be the coordinates of node i. The distance between two points i and j is computed as follows:
double dis = sqrt((pow((double)x[i] - x[j], 2) / 10 + pow((double)y[i] - y[j], 2) / 10 ));
int disInt = (int)dis;
if(disInt < dis) dis = disInt + 1;
else dis = disInt;

具体代码如下:

/********************************************************************************************************************** TSP 算例来自TSPLIB,att48.tsp 数据集,其中有 48 个城市,距离为伪欧式距离* TSPLIB is a library of sample instances for the TSP (and related problems)from various sources and of various types.* 目前最佳解总距离为 10628,其中距离的计算方式为 sqrt((x*x + y*y)/10)* 使用贪心策略求解,解集总距离为 12861,可见贪心策略只是局部最优解
**********************************************************************************************************************/
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<time.h>// 城市数量 N
#define N 48
// 城市距离矩阵
int distance[N][N];/************************************************************************ Function   :init()* Description:从文件中读取城市坐标,并计算城市之间的距离 distance[N][N] * Input      :void* Output     :void* Return     :void***********************************************************************/
void init()
{//城市的 x 和 y 坐标int x[N] = { 0 };int y[N] = { 0 };//从 data.txt 文件读取数据FILE* fp;if ((fp = fopen("..//att48.txt", "r")) == NULL)//if ((fp = fopen("..//kroB100.txt", "r")) == NULL){printf("can not open the file!");exit(0);}while (!feof(fp)){int count;fscanf(fp, "%d", &count);fscanf(fp, "%d%d", &x[count - 1], &y[count - 1]);}fclose(fp);//计算城市之间距离for (int i = 0; i < N - 1; i++){distance[i][i] = 0;              // 对角线为0for (int j = i + 1; j < N; j++){double dis = sqrt((pow((double)x[i] - x[j], 2) / 10 + pow((double)y[i] - y[j], 2) / 10));int disInt = (int)dis;distance[i][j] = dis == disInt ? disInt : disInt + 1;distance[j][i] = distance[i][j];}}distance[N - 1][N - 1] = 0;
}/************************************************************************ Function   :TSPGreedyAlgorithm()* Description:贪心策略求解 TSP 问题* Input      :void* Output     :TSP 路径和对应的总距离* Return     :void***********************************************************************/
void TSPGreedyAlgorithm()
{//总路程int totalDistance = 0;       //默认从 0 开始遍历int current = 0;   //标识城市是否被访问,访问过置为 1bool visit[N] = { false };visit[0] = 1;printf("TSP 路径为:%d ->", 1);//遍历 N - 1 次for (int i = 1; i < N; i++){//设置较大的距离初始值用来选取最近邻int min_distance = 0x7fffffff;//保存当前最近邻城市int temp;//循环选取城市for (int j = 1; j < N; j++){if (!visit[j] && distance[current][j] < min_distance){min_distance = distance[current][j];temp = j;}}visit[temp] = 1;current = temp;totalDistance += min_distance;printf(" %d ->", temp + 1);}totalDistance += distance[current][0];printf(" %d\n", 1);printf("TSP 总距离为:%d\n", totalDistance);
}int main()
{init();TSPGreedyAlgorithm();return 0;
}

结果如下:

可见,贪心算法求解 TSP 问题只能得到局部最优解,如果需要得到最优解,需要采用局部搜索算法等非精确性算法,作者将在后文中继续介绍其他方法求解 TSP 问题。


  1. The multiple traveling salesman problem: an overview of formulations and solution procedures. ↩︎

  2. 计算机算法设计与分析研究,新华出版社,2015.09. ↩︎

  3. 计算机算法基础,西南交通大学出版社,2015.02. ↩︎

贪心算法求解 TSP 旅行商问题及其实现相关推荐

  1. 基于贪心算法求解TSP问题(JAVA)

    前段时间在搞贪心算法,为了举例,故拿TSP来开刀,写了段求解算法代码以便有需之人,注意代码考虑可读性从最容易理解角度写,没有优化,有需要可以自行优化! 详细 代码下载:http://www.demod ...

  2. 人工蜂群算法求解TSP旅行商问题C++(2020.11.13)

    ABC算法求解TSP问题的C++实现 1.输入数据文件:bayg29.tsp 2.头文件 3.所需的类 3.1 城市类City 3.2 包含城市的地图类Graph 3.3 蜜蜂类Bee 3.4 人工蜂 ...

  3. tsp java_基于贪心算法求解TSP问题(JAVA)

    前段时间在搞贪心算法,为了举例,故拿TSP来开刀,写了段求解算法代码以便有需之人,注意代码考虑可读性从最容易理解角度写,没有优化,有需要可以自行优化! 一.TPS问题 TSP问题(Travelling ...

  4. 贪心算法求解TSP问题(python)

    这里使用贪心算法求解TSP问题的python版本 # dist 为距离矩阵,start_index 为起始位置 def tsp_quick(dist: list, start_index: int): ...

  5. branch and bound(分支定界)算法求解TSP旅行商问题

    转载自:分枝定界算法求解TSP 整个程序如下所示: 其中各个模块说明如下: - Timer:计时用. - TSPInstanceReader:TSPLIB标准算例读取用. - PriorityQueu ...

  6. tsp 分支界限 java_干货 | 10分钟教你用branch and bound(分支定界)算法求解TSP旅行商问题...

    在此之前,先给大家讲讲最重要的一个点,搜索树的节点定义,节点定义了原问题的solution和子问题的solution.Node节点定义如下: public class Node {private Ar ...

  7. MATLAB遗传算法GA求解TSP旅行商问题,可选PMX交叉、OX交叉及其它多种交叉方式,在算法中引入2-opt变异算子

    MATLAB遗传算法GA求解TSP旅行商问题,可选PMX交叉.OX交叉及其它多种交叉方式,在算法中引入2-opt变异算子.进化逆转算子提高算法局部搜索能力,利用国际通用的TSPLIB数据集中的eil5 ...

  8. 【路径优化】基于帝企鹅算法求解TSP问题(Matlab代码实现)

    目录 1 帝企鹅算法 2 旅行商问题(TSP) 3 运行结果 4 参考文献 5 Matlab代码实现 1 帝企鹅算法 帝企鹅优化算法(emperor penguin optimizer,EPO)是Ga ...

  9. 蚁群算法求解TSP问题的源代码

    蚁群算法求解TSP问题的源代码 分类: 智能算法2014-05-07 17:25 524人阅读 评论(1) 收藏 举报 蚁群算法 TSP win32程序设计 旅行商问题大都是用遗传算法求解,不过蚁群算 ...

最新文章

  1. (一)win7下cocos2d-x 21 + vs2010
  2. 软件项目管理0709:一个项目经理对产品方案的迷思
  3. 操作系统内存管理——分区、页式、段式管理
  4. Python打造一款多线程端口扫描器
  5. flexbox 伸缩布局
  6. 转jpg java源程序_将pdf文件转成图片并删除java源代码
  7. MySQL 数据库修改登录密码
  8. 采用C编写程序实现从文件读取操作
  9. python每行输出8个式子_多图+代码 | 详解Python操作Excel神器openpyxl的各种操作!
  10. 用python画小黄人-怎么用python画小黄人
  11. Python入门--以主程序的方式运行,if __name__==‘__main__‘
  12. macos big sur 11 完整离线安装包v11.5.2正式版
  13. 2048和多地址入口_七天网站成绩查询官网登录入口地址:http://www.7net.cc/
  14. Drools(2):Drools快速入门
  15. 人机交互-任务4:图形交互界面的设计(web)
  16. YOLOv5中的CSP结构
  17. 浏览器链接打开客户端应用
  18. 不能将值 NULL 插入列 'ID',表 列不允许有 Null 值
  19. 我写代码的这十年——致逝去的青春
  20. 学法医的写代码,学刑侦的做运营……原来阿里人读过那些奇葩专业!

热门文章

  1. 模式先行打造区块链数字积分商城
  2. 如何让Windows 10每天夜间自动开启深色模式
  3. 小尾羊的qt学习之路,01课,基础芝士
  4. 关于计算机经历兼职的英文作文,大学生的兼职工作英语作文
  5. 微信小程序wx.login()登录
  6. 素问·上古天真论原文
  7. php求解一元二次方程,求一元二次方程a*x^2 + b*x + c = 0的根
  8. 分享:作为程序员,为什么你应该学好数学?
  9. 关于java的参考文献英文_java英文参考文献
  10. 宽带上网加速器 免费