基于回溯法求解旅行售货员问题

这篇具有很好参考价值的文章主要介绍了基于回溯法求解旅行售货员问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、实验目的

1.掌握基于回溯的算法求解旅行商问题的原理。

2.掌握编写回溯法求解旅行商问题函数的具体步骤并理解回溯法的核心思想以及其求解过程。

3.掌握子集树以及其他几种解空间树的回溯方法并具备运用回溯算法的思想设计算法并用于求解其他实际应用问题的能力。

4.深刻体会回溯算法求解问题的便利以及感受使用回溯算法所编写程序的明确结构和良好的可读性。

5.从算法设计分析角度,体验回溯法求解问题的方法和思路,从而对旅行商问题基于回溯法求解有更进一步的理解。

二、实验环境

操作系统:Windows10

文本编辑器:VisualStudio Code

所用语言和编译器:C++ g++

实验终端:WindowsPowerShell

三、实验内容

对于以售货员,其需要到若干个城市取推销自己的商品,现已知各个城市之间的路程(或旅行所需的费用,即路的权重),该售货员需要选择一条路线,该路线使得每个城市经过一遍并最后能返回出发的城市,要求总的路程(或旅行所需总的费用总旅费最少)。

城市即城市之间的权重使用邻接矩阵a表示,矩阵a中对应的数值为边的权重(即城市之间路线的消费a[i][j]表示)。

例如若当前城市和该城市路线之间的费用使用如下邻接矩阵表示

-1

30

6

4

30

-1

5

10

6

5

-1

20

4

10

20

-1

通过分析可知,旅行消费的最优解为25,路线为(1,3,2,4,1)。

程序输入为图的顶点个数和各个顶点之间的权重,要求通过算法求解得到旅行消费的最优解和最优路线并输出。

四、算法描述

分析可知,旅行售货员问题的解空间为一棵排列树,对于整个排列数的回溯搜索类似于生成全排列的过程,开始时x=[1,2,……,n],相应的排列树有x[1:n]全排列构成。

在递归函数Backtrack中,当i = n时,当前扩展结点是排列树的叶结点的父结点。此时,回溯算法检测图G是否存在一条从顶点x[n- 1]到顶点x[n]的边和一条从顶点x[n]到顶点1的边。如果这两条边都存在,则找一条旅行商回路。此时,算法还需判断这条回路的费用是否优于已找到的当前最优回路的费用bestc。

如果是,则必须更新当前最优值bestc和当前最优解bestx. 当i < n时,当前扩展结点位于排列树的第i-1层。图G中存在从顶点x[i-1]到顶点x[i]的边时,x[1: i]构成图G的一条路径,且当x[1:i]的费用小于当前最优值时,算法进入排列树的第i层。否则将剪去相应的子树。算法中用变量cc记录当前路径x[1: i]的费用。

如果不考虑更新bestx所需的计算时间,则算法backtrack需要O((n-1)!)计算时间。由于算法backtrack在最坏情况下可能需要更新当前最优解0((n-1)!)次,每次更新bestx需O(n)计算时间,从而整个算法计算复杂性为O(n! )。

求解旅行商问题的回溯函数(backtrack)可以提取为如下几个步骤:

Backtrack函数在搜索状态空间树时,使用二维数组a来表示图,一维数组x表示当前的解数组,bestc定义了当前的值,使用bestx数组定义当前最优解,cc变量定义了当前的路径长度。

  1. :如果i==n,表示搜索到了排列树的底部,首先判断当前是否形成回路并根据当前值和最优值大小关系来更新最优值和最优解。

  1. :若形成了回路(x[n-1]与x[n]连通,x[n]与x[1]连通),则判断当前值是否优于最优值,更新最优值和最优解,若 bestc=-1则说明还没有搜索到一条回路,则先试着求出一个可行解并返回。

  1. :若i不等于n,说明当前在第i层,需要继续搜索。

  1. :判断是否可以进入x[j]子树,x[i-1]与x[j]连通使得1-i层连成一条路径且累计花费优于目前最优值,若可以进入x[j]子树,则交换x[i]与x[j] 并更新路径的长度,进入i+1层。

  1. :返回后,还原路径的长度,比较x[j+1]子树,然后还原之前的解。

代码逻辑如下:

void backtrack(int i)

{

if(i==n){

if(a[x[n-1]][x[n]]!= -1 &&a[x[n]][1]!= -1 ){//说明形成了回路

if(cc+a[x[n-1]][x[n]]+a[x[n]][1]<bestc||bestc==-1){

for(int k=2;k<=n;k++)

bestx[k]=x[k];

bestc=cc+a[x[n-1]][x[n]]+a[x[n]][1];//更新最优值

}

}

return ;

}

else{

for(intj=i;j<=n;j++){

if(a[x[i-1]][x[j]]!=-1&&cc+a[x[i-1]][x[j]]<bestc||bestc==-1){

swap(x[i],x[j]);

cc=cc+a[x[i-1]][x[i]];

backtrack(i+1);

cc=cc-a[x[i-1]][x[i]];

swap(x[i],x[j]);

}

}

}

return ;

}

五、实验结果

第一组输入,设图中有4个顶点,边的个数为6条,城市1和城市2路线之间的权重为30,城市1和城市3路线之间的权重为6,城市1和城市4路线之间的权重为4,城市2和城市3路线之间的权重为5,城市2和城市4路线之间的权重为10,城市3和城市4路线之间的权重为20,通过基于回溯法得算法求解得最优路线为(城市1,城市3,城市2,城市4,城市1),最优值为25。

基于回溯法求解旅行售货员问题

第二组输入,设图中有4个顶点,边的个数为6条,城市1和城市2路线之间的权重为6,城市1和城市3路线之间的权重为30,城市1和城市4路线之间的权重为5,城市2和城市3路线之间的权重为4,城市2和城市4路线之间的权重为20,城市3和城市4路线之间的权重为10,通过基于回溯法得算法求解得最优路线为(城市1,城市2,城市3,城市4,城市1),最优值为25。

基于回溯法求解旅行售货员问题

第三组输入,设图中有3个顶点,边的个数为3条,城市1和城市2路线之间的权重为30,城市1和城市3路线之间的权重为20,城市2和城市3路线之间的权重为1,通过基于回溯法得算法求解得最优路线为(城市1,城市2,城市3,城市1),最优值为51。

基于回溯法求解旅行售货员问题

六、实验总结

本次实验从旅行商问题基于回溯算法求解出发,生动形象的展示了回溯算法在生活中的实用性。关于旅行商问题,该问题是组合优化领域里一个易于描述但却难以处理的NP完全难题,其可能的路径数目与城市的数目是呈指数型增长的。有多种算法可以求解,比如回溯算法和动态规划算法等。通过两种方法的对比学习和这次的回溯算法实现求解,加深了我对旅行商问题和回溯算法进一步的理解。

在本次得代码实现中,对于城市图邻接矩阵得初始化有多种方法,第一种是使用双重for循环遍历二维数组,对每个数组元素赋值。第二种方法是使用memset函数对二维数组表示得邻接矩阵初始化,第三种方法是使用fill函数对二维数组表示得邻接矩阵初始化。其中使用后两种方法初始化矩阵较为方便易懂。

对于fill和memset得使用,由于memset只能按照字节填充字符,对于int类型数组填充只能为0或-1,而使用fill函数初始化可以对数组元素每一个赋任何值,fill函数按照单元赋值,将一个区间的元素都赋同一个值。本次代码使用fill函数对图的邻接矩阵进行初始化,既保证了实现的方便性又保证了赋值的安全性。

进一步了解可知,旅行商问题在很多领域都有所应用,很多问题也都是从旅行商问题延伸和发展的,通过这次旅行商问题的求解,我们可以运用已学过的算法对其他延伸问题进行解决。

使用回溯法求解旅行商问题思路比较清晰,在编程实现时容易调试和修改,并且通过限界函数和约束条件剪枝减少了很多不必要的计算,使得回溯算法求解问题便利高效。学完算法后最有感触的一点就是,算法的精髓并不在于其方式方法,而在于其思想思路。有了算法的思想,那么潜移默化中问题就可以得到解决。

回溯算法的递归通过系统递归栈实现,增加了空间复杂度,但使用递归可以明显减少代码的编写复杂程度,同时使用递归编程时,应注意递归结束条件的编写,防止程序无限运行,造成计算资源的浪费。

通过本次实验,增加了我对限界函数和约束条件剪枝对于减少计算量的认知(求解时间大幅减少),以及在编程中,应根据实际问题出发,通过对比各种实现方式,选取高效简洁同时安全的实现。这些优化空间启发着我不断学习,尝试各种实现和优化,并且对于求解算法问题的道路上遇到的各种问题,应不断求索以实现进步。文章来源地址https://www.toymoban.com/news/detail-490102.html

到了这里,关于基于回溯法求解旅行售货员问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 旅行商问题(回溯算法)

    回溯问题适合于解由向量的形式来构成的,这个向量空间中使用搜索的方法进行搜索,搜索使用宽度优先的方法。货郎问题又名旅行商问题,但其实更多教科书中更通用的叫法叫旅行商问题,下面来对旅行商问题使用回溯算法证明。 有n个城市,已知任两个城市之间的距离,

    2024年02月06日
    浏览(51)
  • 旅行商问题(枚举,回溯,动态规划,贪心,分支界限)

    假设有一个货郎担要拜访n个城市,他必须选择所要走的路程,路程的限制时每个城市只能拜访一次,而且最后要走到原来出发的城市,要求路径长度。 旅行商问题将要走过的城市建立成一个完全图。稠密图,所以用临接矩阵来存。 由于路径的特殊性,可以正走也可以反着走

    2024年02月04日
    浏览(45)
  • 关于旅行商问题的多种算法求解

    一、问题描述 旅行商问题是指旅行家要旅行n个城市,要求每个城市经历一次且仅经历一次然后回到出发城市,并要求所走路程最短。 首先通过所给出的一个无向图,即n个顶点,m个无向边,每条边有一个权值代表两个点之间的距离,要求把每一个点都走一遍并回到原点,求

    2024年02月04日
    浏览(51)
  • Matlab蚁群算法求解旅行商问题

    目录 问题展现 解决代码 代码1 输出结果 代码2 输出结果 代码3 输出结果 假设有一个旅行商人要拜访全国 31 个省会城市,他需要选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择要求是:所选路径的路程为所有路径之中的

    2023年04月15日
    浏览(61)
  • 整数规划——分支界定算法(旅行商问题,规约矩阵求解)

    一、普通优化问题分枝定界求解 题目的原问题为   在计算过程中,利用MATLAB中的linprog()函数进行求解最优解,具体的计算步骤如下: A为约束系数矩阵,B为等式右边向量,C为目标函数的系数向量。   进行第一次最优求解以A=[2 9;11 -8],B=[40;82],C=[-3,-13]利用linprog函数求解。解

    2024年02月16日
    浏览(40)
  • 旅行商问题(TSP)及Python图论求解

    旅行商问题(Traveling Salesman Problem, TSP)是指给定一个城市的集合以及每两个城市之间的距离,找到一条经过每个城市恰好一次且路径最短的回路。 可以想象成一个旅行商要拜访多个城市,问他如何安排路线,使得行程最短。这个问题可能看起来简单,但是随着城市数量的增

    2024年02月12日
    浏览(37)
  • 遗传算法求解旅行商问题(含python源代码)

    目录 前言 编码初始化种群 计算适应度 选择 交叉 变异 完整代码 总结 这次的算法有一点不能确定是否正确,希望有大佬能够批评指正。 遗传算法的一般步骤 种群(population) 指同一时间生活在一定自然区域内,同种生物的所有个体。 所以种群是由个体组成的,所以先需要

    2024年01月23日
    浏览(68)
  • Hopfield神经网络求解旅行商(TSP)问题matlab代码

            1.网络结构         连续Hopfield神经网络(Continuous Hopfield Neural Network,CHNN)的拓扑结构和离散Hopfield神经网络的结构类似,如图11-1所示。连续Hopfield网络和离散Hopfield 网络的不同点在于其传递函数不是阶跃函数,而是连续函数。         与离散型Hopfield神经网络不

    2024年02月14日
    浏览(43)
  • 回溯法求解八皇后问题

    问题提出 :八皇后问题是一个古老而著名的问题。该问题是十九世纪著名的数学家高斯1850 提出在 8x8 格的国际象棋上摆放八皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志

    2023年04月08日
    浏览(57)
  • python实现大规模邻域搜索(LNS)求解旅行商问题(TSP)

    参考《Handbook of Metaheuristics (Third Edition)》中的Large neighborhood search章节, 建议直接阅读英文原版 大规模邻域搜索(LNS) 属于超大邻域搜索(Very Large-Scale Neighborhood Search, VLNS)的一类 ,随着算例规模的增大,邻域搜索算法的邻域规模呈指数增长或者当邻域太大而不能在实际中明确搜索

    2024年02月08日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包