学习链接:

回溯法解旅行商问题(TSP)贪心算法:旅行商问题(TSP)


今天早上做了无数个梦,然后被紧紧地吸附在床上。挣扎一番后爬起来,已经是9点了。然后我开始研究旅行商问题。

在一个无向图中找到一个可以遍历所有节点的一个最短回路。理论上说可以用全排列列出所有解的下标,然后一个一个试,时间复杂度o(n!)。但是可以用回溯法,用【约束函数】(constraint)判断当前路径是否连通,用【界限函数】(bound)判断当前路径是否比已经求得的最短路径小。这两个判断任意一个不符,则做“剪枝操作”(不再对后续节点进行遍历)。

可以看出回溯法比穷举要高明的多。这个回溯法和八皇后问题也有一些区别。TSP问题需要构造一棵排列树:

根节点为{0}

第一层{0,1}

第二层{0,1,2},{0,2,1}

第三层{0,1,2,3},{0,1,3,2},{0,2,1,3},{0,2,3,1},{0,3,1,2},{0,3,2,1}

……

并且回溯法要求对图进行DFS操作,即深度优先搜索。因为需要首先首次找到最深处的节点,才能设置当前最优解,好让后续问题能有参考。

Java代码:

  1. public class Main {
  2.  
  3. public static void main(String[] args) {
  4. int[][] adjMatrix={
  5. {0,20,6,4},
  6. {20,0,5,10},
  7. {6,5,0,15},
  8. {4,10,15,0},
  9. };
  10. TSP problem=new TSP(adjMatrix);
  11.  
  12. }
  13. }
  14.  
  15. class TSP{
  16. int vexnum=0;//顶点数目
  17. int adjMatrix[][];
  18. TSP(int[][] adjMat){
  19. adjMatrix=adjMat;
  20. vexnum=adjMatrix.length;
  21. int init[]={0};
  22. Backtrack(1,init);
  23. int a;
  24. a=0;
  25. }
  26. int bestCost=0;
  27. int[] bestX;//最优解向量
  28. boolean isTraverseDeep=false;
  29. //回溯法递归
  30. //初始x:[0]
  31. void Backtrack(int t,int[] x){//对顶点t进行操作,父结点的解向量是x,
  32. if(t>=vexnum){//解向量的第一个元素应该是初始顶点,如0,最后一个元素也是0
  33. x[t]=0;//最后一个节点赋值:0。
  34. constraint(x,t);
  35.  
  36. }else{//所有顶点都解完
  37. int i,j;
  38. int cx[]=new int[vexnum+1];
  39. for(j=0;j<t;j++) cx[j]=x[j];//拷贝父结点
  40. cx[t]=t;
  41. if(constraint(cx,t)) Backtrack(t+1,cx);//不交换的情况下进行递归
  42. //不断递归调用【Backtrack】,进行DFS
  43. for(i=1;i<t;i++){
  44. cx=new int[vexnum+1];
  45. for(j=0;j<t;j++) cx[j]=x[j];//拷贝父结点
  46. cx[t]=t;
  47. swap(cx,i,t);
  48. if(constraint(cx,t)) Backtrack(t+1,cx);//交换的情况下进行递归
  49. }
  50. }
  51. }
  52. boolean constraint(int[] x,int len){//对解进行约束
  53. int cost=0;
  54. int i;
  55. int pre=x[0];
  56. for(i=1;i<=len;i++){
  57. int dist=adjMatrix[pre][x[i]];
  58. if(dist<=0) return false;//不连通,则为否。约束(constraint)函数
  59. cost+=dist;
  60. pre=x[i];
  61. }
  62. if(isTraverseDeep){//如果已经进行了最底部的遍历,则对这个当前花费进行判别。界限(bound)函数
  63. if(cost<bestCost){//比最优解要小
  64. if(len==vexnum){//已经遍历完
  65. bestCost=cost;
  66. bestX=x;//设置最优解向量
  67. }
  68. return true;
  69. }else return false;
  70. }else if(len==vexnum){//首次遍历到底部
  71. bestCost=cost;
  72. bestX=x;//设置最优解向量
  73. isTraverseDeep=true;
  74. return true;
  75. }
  76. return true;
  77. }
  78. private void swap(int[] nums,int a,int b){
  79. int tmp=nums[a];
  80. nums[a]=nums[b];
  81. nums[b]=tmp;
  82. }
  83. }

回溯法 | 旅行商问题(TSP问题)的更多相关文章

  1. python 回溯法 子集树模板 系列 —— 9、旅行商问题(TSP)

    问题 旅行商问题(Traveling Salesman Problem,TSP)是旅行商要到若干个城市旅行,各城市之间的费用是已知的,为了节省费用,旅行商决定从所在城市出发,到每个城市旅行一次后返回初 ...

  2. NPC问题及其解决方法(回溯法、动态规划、贪心法、深度优先遍历)

    NP问题(Non-deterministic Polynomial ):多项式复杂程度的非确定性问题,这些问题无法根据公式直接地计算出来.比如,找大质数的问题(有没有一个公式,你一套公式,就可以一步步 ...

  3. 回溯法解决N皇后问题(以四皇后为例)

    以4皇后为例,其他的N皇后问题以此类推.所谓4皇后问题就是求解如何在4×4的棋盘上无冲突的摆放4个皇后棋子.在国际象棋中,皇后的移动方式为横竖交叉的,因此在任意一个皇后所在位置的水平.竖直.以及45度 ...

  4. leetcode_401_Binary Watch_回溯法_java实现

    题目: A binary watch has 4 LEDs on the top which represent the hours (0-11), and the 6 LEDs on the bot ...

  5. uva216 c++回溯法

    因为题目要求最多8台电脑,所以可以枚举全排列,然后依次计算距离进行比较,枚举量8!=40320并不大,但这种方法不如回溯法好,当数据再大一些枚举就显得笨拙了,所以这个题我用回溯法做的,回溯有一个好处是 ...

  6. UVa 129 (回溯法) Krypton Factor

    回溯法确实不是很好理解掌握的,学习紫书的代码细细体会. #include <cstdio> ]; int n, L, cnt; int dfs(int cur) { if(cnt++ == ...

  7. 实现n皇后问题(回溯法)

    /*======================================== 功能:实现n皇后问题,这里实现4皇后问题 算法:回溯法 ============================= ...

  8. UVA - 524 Prime Ring Problem(dfs回溯法)

    UVA - 524 Prime Ring Problem Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & % ...

  9. HDU 2553 n皇后问题(回溯法)

     DFS Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u   Description ...

随机推荐

  1. 第九节:EF Core各种迁移指令(CodeFirst和DBFirst)

    一. CodeFirst模式指令 1.前提: 必须的程序集: Microsoft.EntityFrameworkCore.Tools Microsoft.EntityFrameworkCore.Des ...

  2. jax-rs 标准以及 结合 resteasy的使用

    jax-rs:https://baike.baidu.com/item/JAX-RS/10914743?fr=aladdin resteasy:https://www.iteye.com/blog/s ...

  3. 【题解】邻值查找 [CH1301]

    [题解]邻值查找 [CH1301] 传送门:邻值查找 \([CH1301]\) \([AcWing136]\) [题目描述] 给定一个长度为 \(n\) 的序列 \(A\),\(A\) 中的数各不相同 ...

  4. HTML5 下拉控件绑定数据

    <select id="CommunityList" class="form-control" > <option>請選擇社團</ ...

  5. C++中Matrix(矩阵)的基本运算( +、-、=、<<)

    利用二维指针开辟空间形成二维数组: 原题为设计一个Matrix类,实现基本的矩阵运算: 初次设计为HL[10][10]数组,存放矩阵元素,后改为二维指针: 主要问题存在于二维指针理解的不透彻,无法理解 ...

  6. 如何让SQL语句不执行默认排序,而是按照in语句的顺序返回结果

    Oracle: ')order by instr('111,222,333,444,555,666',order_id); Mysql: ') order by instr(',111,222,333 ...

  7. Java中的集合类(List,Set.Map)

    1.List 1.1 Arraylist 与 LinkedList 区别 是否保证线程安全: ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全: 底层数据结构: Arr ...

  8. redis的两种持久化方案

    前言 人生在于折腾系列,网络,多线程等系列博客楼主还在继续折腾也不会放弃.缓存的知识其实并不仅仅在于简单的增删改查,我觉得有必要全面深入的学习一波.记录学习的过程与体悟. RDB 什么是RDB 对re ...

  9. MySQL难点语法——子查询

    本篇主要通过练习来讲解子查询的知识,进入正题之前,先熟悉数据表,表格的数据可以先不用管,主要是熟悉表格的字段名 这里子查询分为三个部分: 1.where条件子查询 这个子查询和普通的查询没什么区别,主 ...

  10. 【python爬虫】每天统计一遍up主粉丝数!

    目录 每天统计一遍up主粉丝数! 第一步,爬取up主的粉丝信息 1.首先导入需要的包 2.为了方便,把它写成一个函数 3.那么就调用一下这个函数吧! 4.运行一下,成功啦! 第二,说好的每天统计一遍呢 ...