7-2 旅行售货员 (10 分)(TSP问题思路加详解)

一题目

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

输入格式:
第一行为城市数n

下面n行n列给出一个完全有向图,如 i 行 j 列表示第 i 个城市到第 j 个城市的距离。

输出格式:
一个数字,表示最短路程长度。

输入样例:

3
0 2 1
1 0 2
2 1 0

输出样例:

3

二:区别回溯法和分支限界法

分支限界法类似于回溯法,也是一种在问题的解空间树T上搜索问题解的算法。但在一般情况下,分支限界法与回溯法的求解目标不同。回溯法的求解目标是找出T中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出使某一目标函数值达到极大或极小的解,即在某种意义下的最优解。
即回溯法是想求出所有的可行解,对解的空间树搜索方式为 DFS
而分支限界想求出的解只有一个最优解,对解的空间树的搜索方式为 BFS
在这里插入图片描述

三:思路

思路:
1.注意题目给出的完全有向图:
有向完全图是指概述图中各边都有方向,且每两个顶点之间都有两条方向相反的边连接的图。
2.通过分析据我们不难发现,每两个顶点间的距离是不一样的
3.写码思路:
<1>:本题解空间是排列树
<2>:我们在遍历树的时候我们采用的BFS,采用的数据结构是优先队列。
<3>:每次在选择扩展结点的时候,我们自定义的排序规则是将已有路径最小的先选择
<4>:选完扩展结点的时候,我们就要处理该扩展结点的邻接点,到达邻接点的距离小于bestw,我们就将该邻接点
统计到队列中
同时更新到达该结点路径程度,记录已经选择的路径顺序(x[i]),因为我们每次选择
的结点不同,所以我们记录的路径顺序也会有变化,那么就需要swap(x[t],x[j]),
这时候,我们就能得到正确的路径顺序。
<5>:当我们要遍历到叶节点的时候,这时候就要更新我们的bestw,将到达最后一个结点的距离加上
最后一个结点到源结点的距离 和 bestw进行比较更新,比其小就更新bestw,
否则,就跳过本轮循环,因为我们我们已经知道了其再往下走,也是不可能比bestw更小了
在这里插入图片描述
在这里插入图片描述

四:上码

/**思路:1.注意题目给出的完全有向图: 有向完全图是指概述图中各边都有方向,且每两个顶点之间都有两条方向相反的边连接的图。2.通过分析据我们不难发现,每两个顶点间的距离是不一样的 3.写码思路:<1>:本题解空间是排列树<2>:我们在遍历树的时候我们采用的BFS,采用的数据结构是优先队列。<3>:每次在选择扩展结点的时候,我们自定义的排序规则是将已有路径最小的先选择<4>:选完扩展结点的时候,我们就要处理该扩展结点的邻接点,到达邻接点的距离小于bestw,我们就将该邻接点统计到队列中 同时更新到达该结点路径程度,记录已经选择的路径顺序(x[i]),因为我们每次选择的结点不同,所以我们记录的路径顺序也会有变化,那么就需要swap(x[t],x[j]),这时候,我们就能得到正确的路径顺序。<5>:当我们要遍历到叶节点的时候,这时候就要更新我们的bestw,将到达最后一个结点的距离加上最后一个结点到源结点的距离 和 bestw进行比较更新,比其小就更新bestw,否则,就跳过本轮循环,因为我们我们已经知道了其再往下走,也是不可能比bestw更小了*/ 
#include<bits/stdc++.h> 
using namespace std;int INF=999999999;
const int N=100;  //const  初始化 
int maps[N][N];   //存储图
int n,m;         //n表示顶点数,m表示边数
int bestw;struct Node
{int x[N];    //解向量,方便从1开始,记录路径int cl;      //表示当前已走过的路径长度int id;     //表示层数
};//重写 优先队列当中排序方法  按每次路径最短的升序处理 
bool operator<(const Node &a,const Node &b){return a.cl>b.cl;
}void bfs()
{priority_queue<Node>q;   Node node;node.cl = 0;   // 0 表示当前已经的走的路径长度,2表示层数node.id = 2;//表示的是每个结点的序号,用于记录树当中路径 for(int i=1;i<=n;i++){node.x[i]=i;}q.push(node);while(!q.empty()){//这个新结点的信息就是上方的node,其解向量为 1,2,3,4...而c = 0 id = 2;  Node newnode=q.top();q.pop();int t;t = newnode.id;//当前层数if(t==n){//当n==4的时候,其实是走了3个结点两个距离,所以还需要判断与最后一个结点//的距离,以及最后一个结点和首节点的距离。//如果两个结点中有一个的距离是无穷的那么,它的路径长度肯定不满足要求	 if(maps[newnode.x[t-1]][newnode.x[n]] != INF && maps[newnode.x[n]][newnode.x[1]] != INF ){//如果满足要求的话,那么就要判断已有的路径长度+到最后一个结点长度//+最后一个结点到源结点的距离。	if(newnode.cl + maps[newnode.x[t-1]][newnode.x[n]]+ maps[newnode.x[n]][newnode.x[1]] < bestw){bestw = newnode.cl+maps[newnode.x[t-1]][newnode.x[n]]+ maps[newnode.x[n]][newnode.x[1]];//更新bestw;} else{//如果我们已经知道其最后的总路程是大于bestw的话,那就没有必要再统计其邻接点了 continue;}}else{//这里也是,如果我们已经知道其到达最后一个结点,或是最后一个结点到达首结点//的距离是无穷的,那么我们就没必要再往下统计了 continue;} } if(newnode.cl >= bestw) continue;//限界条件//拿出队列当中的头节点,扩展其所有的分支 for(int j = t; j <= n; j++){//扩展所有分支//这里是将当前的结点的临界点遍历,但是需要比较已有的路径//长度跟当前的最优值,比其小才遍历,否则的话,再往下进行肯定是比最优值大的 //因为结点层数是比矩阵当中记录的行数多1,所以要减去。 if(newnode.cl + maps[newnode.x[t-1]][newnode.x[j]] < bestw){int c = newnode.cl + maps[newnode.x[t-1]][newnode.x[j]];//生成一个新的结点 且更新现在的路径长度和遍历的树的层数 Node node;node.cl = c;node.id = t+1;//复制父节点的解向量 for(int i = 1; i <= n; i++)node.x[i] = newnode.x[i];//这个交换是为了  扩展结点可以在下一次的加入邻接点(活结点)的时候 //可以正确统计该活结点在矩阵当中的正确行数   swap(node.x[t],node.x[j]);q.push(node);}}}}
int main(){cin>>n;for(int i=1;i<=n;i++){for(int j = 1; j <= n; j++)   {int w;cin >> w;if(w == 0)maps[i][j] = INF;elsemaps[i][j] = w;	}}bestw=INF;bfs();   cout << bestw;
}//3
//0 2 1
//1 0 2
//2 1 0//3 6
//1 2 2
//1 3 1
//2 1 1
//2 3 2
//3 1 2
//3 2 1//4 6
//1 2 15
//1 3 30
//1 4 5
//2 3 6
//2 4 12
//3 4 3//0 15 30 5
//0 0 6 12
//0 0 0 3
//0 0 0 0

在这里插入图片描述

五:总结

下方的博客在处理剪枝的操作并不完美,也就是处理到 最后一个结点和最后一个结点到到首结点的操作有漏洞,我进行了修改,其他地方都值得学习!!
学习自本篇博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/308074.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从零开始内建你的安全测试流程

一、 安全测试的意义安全问题&#xff0c;没发生的时候我们可以侥幸&#xff0c;一旦发生生产安全问题&#xff0c;对很多公司来说可能就是黑天鹅事件了。平台的安全&#xff0c;是我们测试中不可舍弃的一环&#xff0c;而且需要长期持续的关注。二、 从哪里入手很多公司没有专…

『软件测试1』你需要了解的软件测试基础知识

软件测试基础一、 软件缺陷的概述1、什么是软件缺陷2、软件缺陷的类型3、软件缺陷的案例4、软件缺陷的产生原因5、软件缺陷的分类6、软件缺陷的处理流程7、多学一招&#xff1a;缺陷报告&#xff08;由测试人员完成&#xff09;8、常见软件缺陷管理工具9、修复软件缺陷的成本二…

直连路由和静态路由(实验)

一:概念 1:直连路由概念 根据 路由 器学习路由信息、生成并维护 路由表 的方法包括直连路由(Direct)、 静态路由 (Static)和 动态路由 (Dynamic)。直连路由&#xff1a;路由器接口所连接的子网的路由方式称为直连路由&#xff1b; 非直连路由&#xff1a;通过路由协议从别的路…

使用 GB28181.Solution + ZLMediaKit + MediaServerUI 进行摄像头推流和播放

使用 GB28181.Solution ZLMediaKit MediaServerUI 进行摄像头推流和播放独立观察员 2020 年 8 月 25 日一、摄像机 GB28181 配置打开 国标 28181 配置页面&#xff0c;勾上 “接入使能”&#xff1a;打钩的是重要的配置信息&#xff0c;主要就是 SIP 服务器的信息和摄像头自己…

将 .NET Framework 项目转换为 .NET Standard 项目

将 .NET Framework 项目转换为 .NET Standard 项目独立观察员 2020 年 8 月 20 日如今 .NET Core 是未来发展的主流&#xff08;至少在 .NET 5 发布之前&#xff09;&#xff0c;而我们如果要改造一个项目为 .NET Core 项目&#xff0c;则它引用的项目应当先改造为 .NET Standa…

7-3 最短路径 (20 分)(分支限界+思路+详解)

一&#xff1a;题目 给定一个有N个顶点和E条边的无向图&#xff0c;顶点从0到N−1编号。请判断给定的两个顶点之间是否有路径存在。如果存在&#xff0c;给出最短路径长度。 这里定义顶点到自身的最短路径长度为0。 进行搜索时&#xff0c;假设我们总是从编号最小的顶点出发&a…

一份【软件工程】的学习指南已到达,请注意查收!!

软件工程——起始篇一、引言二、学习【软件工程】的原因1、软件设计师证书2、相关领域人员必备技能三、【软件工程】的学习方法1、不要盲目为了学习而学习2、规划学习路线四、结束语【软件工程】应该是大学计算机专业必修的一门课&#xff0c;对于开发者来说&#xff0c;可能有…

『软件工程6』详解软件项目管理之软件范围与估算

软件项目管理——软件范围与估算一、软件项目计划1、目标2、步骤二、软件范围1、软件范围定义2、软件范围——引例三、影响估算的因素四、软件项目资源1、软件项目资源构成2、分析图3、人力资源4、硬件资源5、软件工具6、可复用构件五、软件工作量与成本的估算1、基于LOC估算工…

【翻译】.NET 5 Preview8发布

今天&#xff0c;.NET 5预览8发布了&#xff0c;对于.NET5.0的功能开发已经完成了&#xff0c;这必须要排除待处理的bug&#xff0c;预览8是最后一次预览版本。预计11月正式的.NET5.0版本发布之前还将发布两个正式之前的候选版本&#xff0c;这篇文章描述了.NET5.0版本中的一系…

7-1 页面置换算法--FIFO (50 分)(思路详解)

一:题目 先初始化页面大小&#xff0c;和物理块数。连续输入页面的逻辑地址&#xff0c;以“-1”作为结束标志&#xff0c;采用FIFO页面置换算法、固定分配局部置换分配策略。输出该页面的页号和页内位移&#xff0c;若该页不在内存&#xff0c;并且还有剩余的物理块&#xff…

7-2 页面置换算法--LRU (50 分)

一:题目(思路详解运行时错误解决) 先初始化页面大小&#xff0c;和物理块数。连续输入页面的逻辑地址&#xff0c;以“-1”作为结束标志&#xff0c;采用LRU页面置换算法、固定分配局部置换分配策略。输出该页面的页号和页内位移&#xff0c;若该页不在内存&#xff0c;并且还…

『软件测试3』八大典型的黑盒测试方法已来袭,快快接住!

文章目录一、等价类划分法1、定义2、等价类划分法步骤3、设计测试用例步骤4、案例&#xff1a;学生选修课程二、边界值分析法1、边界值分析法概述2、设计测试用例3、边界值设计原则三、错误推测法1、错误推测法概述2、错误推测法基本思想四、因果图设计法1、因果图设计法概述2、…

使用Jenkins来发布和代理.NetCore项目

Back toStudy!注&#xff1a;书接上文&#xff0c;上回《【CI/CD系列】使用Docker安装Jenkins》咱们说到了使用Docker镜像的方式&#xff0c;来建立Jenkins服务&#xff0c;用来持续集成和持续发布项目&#xff0c;但是上一篇文章有两个问题&#xff1a;01创建的容器不能操作和…

数据库课设(足球联赛管理系统)

一&#xff1a;前言 如果有关注博主的粉丝&#xff0c;可能会发现贴心杰又缺更好几天了&#xff0c;但是我是宠粉杰啊&#xff0c;怎么可能会忘了我的宝贝粉丝呢&#xff0c;只不过是临近期末&#xff0c;各种大作业课设如期而至&#xff0c;这几天我在写数据库课设&#xff0…

.NET Core实用技巧(一)如何将EF Core生成的SQL语句显示在控制台中

前言笔者最近在开发和维护一个.NET Core 项目&#xff0c;其中使用几个非常有意思的.NET Core 相关的扩展&#xff0c;在此总结整理一下。EF Core 性能调优如果你的项目中使用了 EF Core, 且正在处于性能调优阶段&#xff0c;那么了解 EF Core 生成的 SQL 语句是非常关键的。那…

695.岛屿的最大面积(026)BFS

二:思路 1.这里的遍历数据方式为BFS广度遍历 2.当我们遇到一个‘1’的时候,我们就遍历他的左右上下&#xff08;邻接点&#xff09;&#xff0c;如果是1那就入队&#xff0c;直到队列 为空为止。 3.我们记录每个岛屿的面积是采用 我们设置初始值为1&#xff0c;当每遇到一个邻…

『软件工程8』软件项目进度安排与跟踪,一招学会计算关键路径

项目进度安排与跟踪一、项目进度安排的定义及原则1、进度安排的定义2、进度安排的基本原则二、通信开销1、通信开销的定义2、通信路径计算3、案例分析三、工作量分配1、40-20-40规则2、工作量分配图例3、工作量分布推荐四、项目进度安排方法1、关键路径方法(CPM,Critical Path …

await,async 我要把它翻个底朝天,这回你总该明白了吧

一&#xff1a;背景1. 讲故事await&#xff0c;async 这玩意的知识点已经被人说的烂的不能再烂了&#xff0c;看似没什么好说的&#xff0c;但我发现有不少文章还是从理论上讲述了这两个语法糖的用法&#xff0c;懂得还是懂&#xff0c;不懂的看似懂了过几天又不懂了&#xff0…

栈在前端中的应用,顺便再了解下深拷贝和浅拷贝!

详解栈在前端中的应用一、栈是什么二、栈的应用场景三、前端与栈&#xff1a;深拷贝与浅拷贝1、JS数据类型&#xff08;1&#xff09;js数据类型的分类&#xff08;2&#xff09;js数据类型的定义和存储方式&#xff08;3&#xff09;js数据类型的判断方式2、深究浅拷贝和深拷贝…

计网课设 模拟实验拓扑

一:前言 幸福的是考完两科了&#xff0c;抽出时间赶紧赶赶课设&#xff0c;两周遇到了好多事&#xff0c;开心的&#xff0c;烦心的&#xff0c;一堆堆的压过来&#xff0c;但庆幸自己迷失不太久&#xff0c;又能继续学习了 二&#xff1a;实验概览 1:实验拓扑图 2:实验要求…