问题描述

 某售货员要到若干城市去推销商品,已知各城市之间的路程,他要选定一条从驻地出发,经过每个城市一遍,最后回到住地的路线,使总的路程最短。
   

  结果为: 1 3 2 4 1

算法描述

 回溯法,序列树, 假设起点为 1。

 算法开始时 x = [1, 2, 3, …, n]

 x[1 : n]有两重含义 x[1 : i]代表前 i 步按顺序走过的城市, x[i + 1 : n]代表还未经过的城市。利用Swap函数进行交换位置。

 若当前搜索的层次i = n 时,处在排列树的叶节点的父节点上,此时算法检查图G是否存在一条从顶点x[n-1] 到顶点x[n] 有一条边,和从顶点x[n] 到顶点x[1] 也有一条边。若这两条边都存在,则发现了一个旅行售货员的回路(即:新旅行路线),算法判断这条回路的费用是否优于已经找到的当前最优回路的费用bestcost,若是,则更新当前最优值bestcost和当前最优解bestx。

 若i < n 时,检查x[i - 1]至x[i]之间是否存在一条边, 若存在,则x [1 : i ] 构成了图G的一条路径,若路径x[1: i] 的耗费小于当前最优解的耗费,则算法进入排列树下一层,否则剪掉相应的子树。

递归回溯

  • 回溯法对解空间作深度优先搜索
  • 通常用递归方法实现回溯法

void backtrack (int t)
{if (t>n) output(x);// t>n时已搜索到一个叶结点, output(x)对得到的可行解x进行记录或输出处理.else{                                     for (int i=f(n,t);i<=g(n,t);i++) { // 函数f和g分别表示在当前扩展结点处未搜索子树的起止编号.                            x[t]=h(i); //h(i)表示在当前扩展结点处x[t]的第i个可选值if (constraint(t)&&bound(t)) backtrack(t+1);} //for循环结束后, 已搜索遍当前扩展结点的所有未搜索子树.}
} //Backtrack(t)执行完毕, 返回t-1层继续执行, 对未测试过的x[t-1]的值继续搜索.
  • if (Constraint(t)&&Bound(t) ) Backtrack(t + 1);if语句含义:Constraint(t)和Bound(t)表示当前扩展节点处的约束函数和限界函数。
  • Constraint(t): 返回值为true时,在当前扩展节点处x[1:t]的取值问题的约束条件,否则不满足问题的约束条件,可剪去相应的子树
  • Bound(t): 返回的值为true时,在当前扩展节点处x[1:t]的取值为时目标函数越界,还需由Backtrack(t+1)对其相应的子树做进一步搜索。否则,当前扩展节点处x[1:t]的取值是目标函数越界,可剪去相应的子树
  • for循环作用:搜索遍当前扩展的所有未搜索过的子树。
  • 递归出口:Backtrack(t)执行完毕,返回t-1层继续执行,对还没有测试过的x[t-1]的值继续搜索。当t=1时,若以测试完x[1]的所有可选值,外层调用就全部结束。

迭代回溯

  采用树的非递归深度优先遍历算法,可将回溯法表示为一个非递归迭代过程。

void iterativeBacktrack ( )
{int t=1;while (t>0) {if (f(n,t)<=g(n,t)) for (int i=f(n,t);i<=g(n,t);i++) {// 函数f和g分别表示在当前扩展结点处未搜索子树的起止编号.x[t]=h(i);if (constraint(t)&&bound(t)) {if (solution(t)) output(x); //solution(t)判断当前扩展结点处是否已得到问题的一个可行解                                       else t++;} //solution(t)为假,则仅得到一个部分解,需继续纵深搜索}else t--;} //while循环结束后,完成整个回溯搜索过程
}

子集树与排列树

  • 子集树: 所给的问题是从n个元素的集合中找出满足某种性质的子集时, 相应的解空间称为子集树.

  子集树通常有2n个叶结点, 遍历子集树的任何算法均需Ω(2n)的计算时间.

  例如: 0-1背包问题的解空间为一棵子集树.

  • 排列树: 当所给的问题是确定n个元素满足某种性质的排列时, 相应的解空间称为排列树.

  排列树通常有(n-1)!个叶结点, 遍历排列树需要Ω(n!)的计算时间.

  例如: 旅行售货员问题的解空间为一棵排列树.

代码实现

#include <bits/stdc++.h>
using namespace std;
const int max_ = 0x3f3f3f;   //定义一个最大值
const int NoEdge = -1;      //两个点之间没有边
int citynum;                //城市数
int edgenum;                //边数
int currentcost;            //记录当前的路程
int bestcost;               //记录最小的路程(最优)
int Graph[100][100];        //图的边距记录
int x[100];                 //记录行走顺序
int bestx[100];             //记录最优行走顺序void InPut()
{int pos1, pos2, len;     //点1 点2 距离cout<<"请输入城市数和边数(c e):";cin>>citynum>>edgenum;memset(Graph, NoEdge, sizeof(Graph));cout<<"请输入两座城市之间的距离(p1 p2 l):"<<endl;for(int i = 1; i <= edgenum; ++i){cin>>pos1>>pos2>>len;Graph[pos1][pos2] = Graph[pos2][pos1] = len;}
}//初始化
void Initilize()
{currentcost = 0;bestcost = max_;for(int i = 1; i <= citynum; ++i){x[i] = i;}
}void Swap(int &a, int &b)
{int temp;temp = a;a = b;b = temp;
}void BackTrack(int i) //这里的i代表第i步去的城市而不是代号为i的城市
{if(i == citynum){//进行一系列判断,注意的是进入此步骤的层数应是叶子节点的父节点,而不是叶子节点if(Graph[x[i - 1]][x[i]] != NoEdge && Graph[x[i]][x[1]] != NoEdge && (currentcost + Graph[x[i - 1]][x[i]] + Graph[x[i]][x[1]] < bestcost || bestcost == max_)){//最小(优)距离=当前的距离+当前城市到叶子城市的距离+叶子城市到初始城市的距离bestcost = currentcost + Graph[x[i - 1]][x[i]] + Graph[x[i]][x[1]];for(int j = 1; j <= citynum; ++j)bestx[j] = x[j];}}else{for(int j =  i; j <= citynum; ++j){if(Graph[x[i - 1]][x[j]] != NoEdge && (currentcost + Graph[x[i - 1]][x[j]] < bestcost || bestcost == max_)){Swap(x[i], x[j]);  //这里i 和 j的位置交换了, 所以下面的是currentcost += Graph[x[i - 1]][x[i]];currentcost += Graph[x[i - 1]][x[i]];BackTrack(i + 1);   //递归进入下一个城市currentcost -= Graph[x[i - 1]][x[i]];Swap(x[i], x[j]);}}}
}void OutPut()
{cout<<"最短路程为:"<<bestcost<<endl;cout << "路线为:" << endl;for(int i = 1; i <= citynum; ++i)cout << bestx[i] << " ";cout << "1" << endl;
}int main()
{InPut();Initilize();BackTrack(2);OutPut();
}

样例测试

以前面的样例示范

输入

请输入城市数和边数(c e):4 6
请输入两座城市之间的距离(p1 p2 l):
1 2 30
1 3 6
1 4 4
2 4 10
2 3 5
3 4 20

输出
最短路程为:25
路线为:
1 3 2 4 1

旅行售货员问题-回溯法相关推荐

  1. 回溯子集树与排列树——装载问题旅行售货员问题(算法设计课题)

    *对回溯法不是很理解的请移步博客http://blog.csdn.net/sm9sun/article/details/53244484 掌握了回溯法以后,我们给出两种定义: 当所给问题是从n个元素的 ...

  2. [回溯算法] 五大常用算法之回溯法

    算法入门6:回溯法 一. 回溯法 – 深度优先搜素 1. 简单概述 回溯法思路的简单描述是:把问题的解空间转化成了图或者树的结构表示,然后使用深度优先搜索策略进行遍历,遍历的过程中记录和寻找所有可行解 ...

  3. 五大常用算法之回溯法详解及经典例题

    一. 回溯法 – 深度优先搜素 1. 简单概述 回溯法思路的简单描述是:把问题的解空间转化成了图或者树的结构表示,然后使用深度优先搜索策略进行遍历,遍历的过程中记录和寻找所有可行解或者最优解. 基本思 ...

  4. java 着色问题 回溯算法,C语言使用回溯法解旅行售货员问题与图的m着色问题

    旅行售货员问题 1.问题描述: 旅行售货员问题又称TSP问题,问题如下:某售货员要到若干个城市推销商品,已知各城市之间的路程(或旅费),他要选定一条从驻地出发,经过每个城市一遍最后回到驻地的路线,使总 ...

  5. 回溯法——旅行售货员问题

    旅行售货员问题即给几个地点,相互之间有路径,有每个路径对应的消耗的费用.我们将起点设为1,其他地点设为2,3,4-n.我们起初将所有路径费用都设置成∞,然后再输入 相通路径的费用,再更新费用值.我们以 ...

  6. 回溯法----旅行售货员问题

    一.问题 同文章 <分支限界法----旅行售货员问题> 二.代码实现 程序实现了 递归回溯 解决该问题 迭代回溯算法仍在考虑中... /************************** ...

  7. 回溯法、分支限界法两种思想帮你轻松搞定旅行售货员问题(TSP)

    问题描述 某售货员要到若干城市去推销商品,已知各城市之间的路线(或旅费).要选定一条从驻地出发,经过每个城市一遍,最后回到驻地的路线,使总的路程(或总旅费)最小.本文只考虑4个城市的情况,下面这个带权 ...

  8. 【算法导论07】回溯法-旅行售货员问题

    07回溯法-旅行售货员问题 问题描述: 已知有m个城市,城市之间由n条不同长度的道路相连.一个售货员从一座城市出发,途径所有城市,并最终回到原点,设计算法计算售货员所走的最短路径结点. 问题分析: 从 ...

  9. 算法设计与分析——回溯法——旅行售货员问题

    #include<iostream> #include<bits/stdc++.h> using namespace std; const int noEdge=65535; ...

最新文章

  1. 如何使用MATLAB绘制不同类型的二维图形
  2. gRPC学习记录(二)--Hello World
  3. [GO语言基础] 三.变量声明、数据类型、标识符及编程练习12题
  4. ORA-28056:Writing audit records to Windows Even...
  5. Dubbo的发展历史
  6. WebAPI(part9)--下拉菜单及留言案例
  7. mysql 数学函数
  8. powerpoint文字教程
  9. 在pocket pc 2003上播放声音
  10. Android图形显示系统——下层显示1:基础知识与相关文件
  11. c语言文件读入到链表函数fscanf,【求解答】c关于把文件数据放进链表,并将链表遍历...
  12. 几种常见的 Kafka 集群监控工具
  13. 如何使用中国知网查询文献,并自动生成参考文献格式引文?
  14. deepin恢复出厂_初始化 - deepin Wiki
  15. kali-linux-2022 下载/系统/权限/中文/配置/换源等问题一次解决
  16. ZYNQ启动流程之分析BootRoM
  17. php ses 发送邮件,Amazon SES – 通过PHP sdk发送HTML邮件
  18. 【socket】socket介绍-socket与http服务通信
  19. c 语言 如何设置串口波特率,串口自动波特率设置程序
  20. 1万的android手机推荐,Vertu推天价Android手机:入门级售价1万美元

热门文章

  1. pr转场 卡通炫酷图形动画视频转场pr模板mogrt
  2. 【第十五届蓝桥杯备赛(bushi,写文凑个数)】蓝桥OJ---排列序数
  3. 部分APP无法代理抓包的原因及解决方法(flutter 应用抓包)
  4. 文字转语音并生成音频文件
  5. 传统供应链向智慧供应链转型之道
  6. LetsEncrypt与Certbot之certbot命令介绍
  7. 在家办公是什么感觉?
  8. 物理机可ping通虚拟机,虚拟机无法ping通物理机
  9. 网络舆情分析技术 读书笔记2
  10. Stata: 超级强大的 gtools 命令组