回溯法 | 旅行商问题(TSP问题)
学习链接:
回溯法解旅行商问题(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代码:
public class Main {
public static void main(String[] args) {
int[][] adjMatrix={
{0,20,6,4},
{20,0,5,10},
{6,5,0,15},
{4,10,15,0},
};
TSP problem=new TSP(adjMatrix);
}
}
class TSP{
int vexnum=0;//顶点数目
int adjMatrix[][];
TSP(int[][] adjMat){
adjMatrix=adjMat;
vexnum=adjMatrix.length;
int init[]={0};
Backtrack(1,init);
int a;
a=0;
}
int bestCost=0;
int[] bestX;//最优解向量
boolean isTraverseDeep=false;
//回溯法递归
//初始x:[0]
void Backtrack(int t,int[] x){//对顶点t进行操作,父结点的解向量是x,
if(t>=vexnum){//解向量的第一个元素应该是初始顶点,如0,最后一个元素也是0
x[t]=0;//最后一个节点赋值:0。
constraint(x,t);
}else{//所有顶点都解完
int i,j;
int cx[]=new int[vexnum+1];
for(j=0;j<t;j++) cx[j]=x[j];//拷贝父结点
cx[t]=t;
if(constraint(cx,t)) Backtrack(t+1,cx);//不交换的情况下进行递归
//不断递归调用【Backtrack】,进行DFS
for(i=1;i<t;i++){
cx=new int[vexnum+1];
for(j=0;j<t;j++) cx[j]=x[j];//拷贝父结点
cx[t]=t;
swap(cx,i,t);
if(constraint(cx,t)) Backtrack(t+1,cx);//交换的情况下进行递归
}
}
}
boolean constraint(int[] x,int len){//对解进行约束
int cost=0;
int i;
int pre=x[0];
for(i=1;i<=len;i++){
int dist=adjMatrix[pre][x[i]];
if(dist<=0) return false;//不连通,则为否。约束(constraint)函数
cost+=dist;
pre=x[i];
}
if(isTraverseDeep){//如果已经进行了最底部的遍历,则对这个当前花费进行判别。界限(bound)函数
if(cost<bestCost){//比最优解要小
if(len==vexnum){//已经遍历完
bestCost=cost;
bestX=x;//设置最优解向量
}
return true;
}else return false;
}else if(len==vexnum){//首次遍历到底部
bestCost=cost;
bestX=x;//设置最优解向量
isTraverseDeep=true;
return true;
}
return true;
}
private void swap(int[] nums,int a,int b){
int tmp=nums[a];
nums[a]=nums[b];
nums[b]=tmp;
}
}
回溯法 | 旅行商问题(TSP问题)的更多相关文章
- python 回溯法 子集树模板 系列 —— 9、旅行商问题(TSP)
问题 旅行商问题(Traveling Salesman Problem,TSP)是旅行商要到若干个城市旅行,各城市之间的费用是已知的,为了节省费用,旅行商决定从所在城市出发,到每个城市旅行一次后返回初 ...
- NPC问题及其解决方法(回溯法、动态规划、贪心法、深度优先遍历)
NP问题(Non-deterministic Polynomial ):多项式复杂程度的非确定性问题,这些问题无法根据公式直接地计算出来.比如,找大质数的问题(有没有一个公式,你一套公式,就可以一步步 ...
- 回溯法解决N皇后问题(以四皇后为例)
以4皇后为例,其他的N皇后问题以此类推.所谓4皇后问题就是求解如何在4×4的棋盘上无冲突的摆放4个皇后棋子.在国际象棋中,皇后的移动方式为横竖交叉的,因此在任意一个皇后所在位置的水平.竖直.以及45度 ...
- 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 ...
- uva216 c++回溯法
因为题目要求最多8台电脑,所以可以枚举全排列,然后依次计算距离进行比较,枚举量8!=40320并不大,但这种方法不如回溯法好,当数据再大一些枚举就显得笨拙了,所以这个题我用回溯法做的,回溯有一个好处是 ...
- UVa 129 (回溯法) Krypton Factor
回溯法确实不是很好理解掌握的,学习紫书的代码细细体会. #include <cstdio> ]; int n, L, cnt; int dfs(int cur) { if(cnt++ == ...
- 实现n皇后问题(回溯法)
/*======================================== 功能:实现n皇后问题,这里实现4皇后问题 算法:回溯法 ============================= ...
- UVA - 524 Prime Ring Problem(dfs回溯法)
UVA - 524 Prime Ring Problem Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & % ...
- HDU 2553 n皇后问题(回溯法)
DFS Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Description ...
随机推荐
- 大数据基础总结---MapReduce和YARN技术原理
Map Reduce和YARN技术原理 学习目标 熟悉MapReduce和YARN是什么 掌握MapReduce使用的场景及其原理 掌握MapReduce和YARN功能与架构 熟悉YARN的新特性 M ...
- Java并发专栏(一)—— Process vs Thread
一.前言 程序是代码和数据的集合,是一种静态实体.不具有代码执行和数据处理的能力,更多是一种行为的描述. 如果将程序和处理器结合,处理器将程序加载至内存,然后执行程序代码处理数据.这时就是可执行的程序 ...
- 通用高效字符串匹配--Sunday算法
字符串匹配(查找)算法是一类重要的字符串算法(String Algorithm).有两个字符串, 长度为m的haystack(查找串)和长度为n的needle(模式串), 它们构造自同一个有限的字母表 ...
- Golang中,Aes加解密
今天在用Golang解析php那边用Aes加密的一个key.网上大多是用base64将结果编码一下.而且用到了向量.我php 那边没有用到向量.所以golang这边也是要去掉的.参考网站的改了下.能够 ...
- DjangoDRF总结
思维导图xmind文件:https://files-cdn.cnblogs.com/files/benjieming/DRF%E6%A8%A1%E5%9D%97.zip
- Unity Ioc 依赖倒置及Untity AOP被动拦截/自动拦截
各位博友金安,首先声明这是一篇转载的博客,原文链接:https://www.cnblogs.com/scottpei/archive/2013/01/08/2851087.html 十年河东,十年河西 ...
- 前端Q的小小小里程碑
很多关注我的人都不太了解前端Q这个名字的由来,这篇文章就来讲讲前端Q的前世今生,顺便送大大福利(文末有惊喜),哈哈-- 恭喜!前端Q总用户数突破千啦~~ 前端Q前世 前端Q这个公众号,其实很早很早的时 ...
- js中的原型,原型链和继承
在传统的基于Class的语言如Java.C++中,继承的本质是扩展一个已有的Class,并生成新的Subclass. 由于这类语言严格区分类和实例,继承实际上是类型的扩展.但是,JavaScript最 ...
- i春秋——“百度杯”CTF比赛 十月场——GetFlag(md5碰撞、文件包含、网站绝对路径)
需要提交的captcha满足等式,肯定就是MD5碰撞了 附上脚本 import hashlib def func(md5_val): for x in range(1,100000000): md5_ ...
- WPE 过滤器 高级滤镜
与普通滤镜区别就是: 普通滤镜固定位置 高级滤镜固定数值 普通滤镜 指定位置1~6,对应发送数据的固定1~6字节 高级滤镜 首先,勾选高级-自发现有连锁位置 记得,偏移001对应修改000位置,也可称 ...