递推与储存,是动态规划的关键



小智最近由于项目需要,经常要接触到一些规划类的问题。那今天就给大家讲一讲旅行商问题及其解法吧。


旅行商问题,即TSP问题(Travelling Salesman Problem)。问题是,有一个旅行商人要拜访n个城市,每个城市只能拜访一次,而且最后要回到原来出发的城市。这位商人如何设计拜访顺序,使走过的路径最短? 


这种求最短距离问题有非常多实际场景会涉及到,比如,快递公司为了使城市A到城市B的快递件运输速度达到最快,他们会选择城市A到城市B的最短路径来进行运输。再比如,游戏当中的角色移动时,需要寻找到一条最短路径进行移动,这样游戏中的角色才不会失真。又比如,网络当中需要有路由算法,用于计算最短的信息跳转路径。


一款RPG游戏的角色移动演示,你会发现角色走路沿最短路径。如果不这样设计,游戏的体验感则会非常糟糕


这么多实际的精彩案例,旅行商问题确实值得研究,而且学习完说不定能派上用场。


对于这类问题,我个人这次倾向使用动态规划算法来解这道问题,得到他的精确解。


动态规划这种技术也是有非常多实际场景会涉及到,比如,以动态规划为基础原理的维特比算法,现今常用于语音识别这个领域。再比如,生物信息学中需要进行DNA之间的比对,找出最长的公共DNA部分。


语音识别技术使得人机交互的难度不断下降,其背后离不开数学


这里首先讲解一下动态规划的步骤:

1、分段:将原问题分解为若干个相互重叠的子问题。

2、分析:分析问题,找出递推式。

3、求解:利用递推式自底向上计算,实现动态规划过程。


其实,动态规划的精妙之处在于,每个子问题只求解一次,并将解保存在一个表格中,当需要再次求解此子问题时,只是简单地通过查表获得该子问题的解,避免大量的重复计算。


为了更好地在旅行商问题上讲解动态规划算法,这里讲一个简单的例子,隔壁村的老王要去这4座城市拜访,城市之间的距离如下图。


四座城市之间的距离示意图


图中一共有4座城市,城市0、城市1、城市2、城市3。小智目测走完这几个城市的最短路程为10(城市0→城市1→城市2→城市3→城市0)


人总是有直觉,而且有时会非常准。


当然,我们要用科学而完整的方法而得到最短的拜访路径,不能总是依赖直觉,尽管直觉经常是对的。我们先用穷举法列一下所有路径:



这是暴力的穷举法,一共需要运算3!×4=24次加法。


暴力法是能得到结果,但是时间复杂度是阶乘阶O(n!),是算法当中复杂度极高的等级。

常见的算法时间复杂度由小到大依次为:

常数阶Ο(1)<对数阶Ο(logn)<线性阶Ο(n)<线性对数阶Ο(nlogn)<平方Ο(n^2)<立方阶Ο(n^3)<…<指数阶Ο(2^n)<阶乘阶Ο(n!)。

 

从动态规划的角度看,假如我们找到一条最短的路径:城市0→城市1→城市2→城市3→城市0


那么,城市1→城市2→城市3→城市0必然是城市1到城市0的一条最短路径。

假设该路径不是城市1到城市0的一条最短路径,设该路径的总路程为d,那么会有一条新的路径作为城市1到城市0的最短路径d’, d > d’,那么城市0→新路径→城市0为完成拜访的最短路径,与原假设”找到一条最短路径:城市0→城市1→城市2→城市3→城市0”矛盾。


按照上述结论,可以将路径进行分解。设最短路径的符号标记为 L。那么:


L(城市0→城市0) = L(城市0→城市1) + L(城市1到城市0)


请注意,城市0是起点城市和终点城市。


假如已经获知各座城市到城市0的最短路径,那么从城市0到城市0归结起来一共有三种路径:


L(城市0→城市1) + L(城市1到城市0)

L(城市0→城市2) + L(城市2到城市0)

L(城市0→城市3) + L(城市3到城市0)


在上述路径找到最短的路径,即为拜访所有城市的最短路径。


上述路径可以继续分解。比如,以第1条路径为例:


L(城市1到城市0) = L(城市1→城市2) + L(城市2到城市0)


就这样,路径一直可以被分解,到什么时候结束呢?假设继续以上述的L(城市1到城市0)为例,继续对L(城市2到城市0)进行分解:


L(城市2到城市0) = L(城市2→城市3) + L(城市3到城市0)


由于城市1、城市2之前已经出现过了,因此L(城市3到城市0)只能等于L(城市3→城市0)


至此,城市间的路径全部可以被分解。


我们以符号来表达上述的过程。假设 d(i, V) 表示从城市 i经过城市集合 V各点一次后返回到出发点的最短距离。d(i, V) 可以按照一下方式分解:




其中,Cki 为城市 k 到城市的距离。


这样,动态规划的递推式出来了。


从城市0出发,经过城市1、2、3后回到城市0的最短路径长度为:



这个是最后一个阶段的决策,它必须依据 d(1, {2,3})d(2, {1,3}) 和 d(3, {1,2})的计算结果,继续分解:



当然,还可以继续进行分解:



上述过程可以发现,在计算的时候,可以不断引用先前的计算结果,这就是动态规划的特点。我们将上述过程在表格中把填写一下:



至此,发现拜访完所有城市的最短距离为10,印证了小智原来的想法。


上述执行加法的次数:



时间复杂度为O(2n)。动态规划相比起穷举法下降了一个等级,这个算法起到了重要的价值。


完成原理阐述,是时候写代码了,先整理一下伪代码:

1、初始化一个表格d,用于记录计算结果。并以距离初始化第0列

2、循环j=1:2n-1-1

循环 i=(1:n,且不包含在V[j])

        循环 V[j]中的所有元素

         d[i][j] = min(c[i,k], d[k][V[j]去掉k元素后对应的序号])

3、计算d[0][2n-1-1] = min(c[0,k] +d[k][2n-1-2],此为最短路径长度


这里需要注意的是,集合V是从小变大,要先算V较小的部分,因此要找一个方式来表达集合V,然后对计算进行顺序。


这里将数字转换为二进制序列,以表示集合V拥有的元素,比如:[1,0,0],可表示集合V只包含元素1,[0,1,1],可表示集合V包含元素2和元素3。


二进制数可以映射到自然数区,比如:


0 →[0,0,0]、1 → [1,0,0]、2 → [0,1,0]、3 → [1,1,0]

4 →[0,0,1]、5 → [1,0,1]、6 → [0,1,1]、7 → [1,1,1]


为了实现集合从小到大的计算顺序,对二进制序列进行特别的排序,其中第一排序条件是序列的总和,升序。第二排序条件是序列代表的数字,升序,转换为以下排序。



这样,按照上述表格中的序号作为顺序进行计算即可。


可以动手编程了。我们挑一道更难的题目,有10座城市的TSP问题:


另一道题目:10座城市之间的距离矩阵


有了想法很快就可以付诸实践了(回复“TSP程序”可以获得程序),这是最美妙的地方。按照上述流程,最短路径距离为284,最短路线:


0→3→1→5→7→6→2→8→4→9→0


当然,这个并不是一个完美的解法,随着城市数量的增加,计算难度呈指数增长,目前关于TSP在多项式时间内的解法目前还没出现,但我相信未来一定会诞生。


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

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

相关文章

dotnet core TargetFramework 解析顺序探索

dotnet core TargetFramework 解析顺序测试Intro现在 dotnet 的 TargetFramework 越来越多,抛开 .NET Framework 不谈,如果一个类库支持多个 TargetFramework 应用实际运行的时候会使用哪个版本的 API 呢,之前一直都是想当然的自以为是了&…

大数据时代,掌握数据分析需要做到这几点

这些年来,随着进入大数据时代,各行各业均有一个词频频被提到,那就是数据分析。那么数据分析究竟是什么呢?数据分析就是指用适当的统计分析方法对收集来的大量数据进行处理分析,提取有用信息并形成结论,从而…

93.7%的程序员!竟然都不知道Redis为什么默认16个数据库?

背景在实际项目中redis常被应用于做缓存,分布式锁/消息队列等。但是在搭建配置好redis服务器后很多朋友应该会发现和有这样的疑问,为什么redis默认建立了16个数据库,16个数据库的由来redis是一个字典结构的存储服务器,一个redis实…

“一边熬夜一边求不要猝死”,90后养生朋克指南,条条扎心!

随着一批又一批的90后步入中年秃头、失眠、衰老...健康的压力如影如随是时候开始养生朋克了当代青年:养生朋克指南养生朋克一边作死一边自救的养生方式比如一边熬夜一边涂贵价护肤品用最贵的眼霜 熬最长的夜心理活动经常是:一边熬夜一边祈祷自己不要猝死…

万级 K8S 集群背后,etcd 如何保持稳定性?

这几年,随着 Kubernetes 成为容器编排领域霸主,etcd 越来越火,GitHub star 已超过 34.2K。这与它的应用场景广泛密不可分,从服务发现到分布式锁,从配置存储到分布式协调,可以说,etcd 已成为云原…

qdialog 只有点击才能获得焦点_4 个突破点,让你的 Banner 点击率提升10倍

双 11 刚过,双 12又来了每年这个时候作为一名设计师,真的很难...老板压着做电商 banner还有很多人指指戳戳让你改稿好不容易按照别人的想法过稿结果banner 的点击率还不高其实,只需要稍微调整视觉重点你的电商banner 就会变得变得更吸引人&am…

穿背心的老院士,86岁,重病,还在敲代码,单手!

昨天有幸看到了一个视频,视频中,一位老先生穿着朴素的白背心,伏在桌上,对着电脑,一手按着写满密密麻麻数学公式的本子,另一只手仅用单指吃力又缓慢地按着键盘。老先生全神贯注地研究他是 “背心院士” 高伯…

百度广告点击软件_结束了,百度 “毒瘤” 广告!

“ 通过本文,你可以获取一款上网必备的插件,让你摆脱各种"毒瘤"广告。”大家天天逛网页,最恼人的也就是广告了吧。尤其是百度搜索时。01—毒瘤广告有多愁?百度广告有多可怕,小哥哥给你演示一下。百度搜“智齿…

java跳转画面后画面白了_如何跳转指定页面后再次跳转到另一页面或原来的页面...

c#图解教程第5版数万读者认可的新99.33元(需用券)去购买 >这里可以采用redirect以get形式向指定页面发出get请求,指定页面完成后会再次跳转到redirect后边指定的页面(注意:这里的redirect只是一个自定义参数,并不是自带的,名称…

【基础数学知识】带你理解泰勒展开式本质

推荐阅读时间:5min~8min主要内容:更好的理解,并且记忆泰勒展开式我们学习泰勒展开,本质上就是为了在某个点附近,用多项式函数取近似其他函数。可能有些童鞋就要问了,既然有一个函数了,为什么还需…

C#使用NPOI进行word的读写

目录一、简介1、操作Word的类库:二、简单使用1、XWPFDocument类的实例化2、设置页面的大小3、段落处理4、表格处理5、页眉页脚处理三、综合示例四、参考一、简介1、操作Word的类库:二、简单使用1、XWPFDocument类的实例化该类的实例对应一个word文档XWPF…

weblogic修改控制台ip_「Weblogic学习」Weblogic知识要点之JNDI/JTA编程开发

给它一个名字,它就能提供你要的服务,JNDI就是这么地任性。想任性的霸占数据?JTA为你把风。这期,谈谈JNDI和JTA的简单介绍,一起看看吧……JNDI编程JNDI(Java Naming and Directory Interface)是SUN公司提供的一种标准的…

java不适合开发cv吗_JavaCV开发环境的配置

一.安装opencv2.4.4、测试运行OpenCV-2.4.4.exe,就是解压,把它解压到一个你喜欢的地方 ——1.1 路径最好不要太深,点啊点的最讨厌了2. 添加 ***\OpenCV2.4.4\build\x64\vc11\bin; 到环境变量的PATH后面 ——2.1 ***是你放OpenCV2.4.4的地方…

NA-NP-IE系列实验5:配置文件的备份和IOS 的备份

实验5:配置文件的备份和IOS 的备份<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />1. 实验目的通过本实验&#xff0c;读者可以掌握如下技能&#xff1a;&#xff08;1&#xff09; 熟悉TFTP 服务器的使用&#xff08;2&#xf…

浅析 Sunday 算法

背景Sunday 算法是 Daniel M.Sunday 于 1990 年提出的字符串模式匹配。其效率在匹配随机的字符串时比其他匹配算法还要更快。Sunday 算法的实现可比 KMP&#xff0c;BM 的实现容易太多。算法过程假定主串为 "HERE IS A SIMPLE EXAMPLE"&#xff0c;模式串为 "EX…

.NET 6 Preview 1发布!

喜欢就关注我们吧&#xff01;.NET 6 首个预览版已发布&#xff0c;官方表示 .NET 6 的核心目标是完成从 .NET 5 开始的 .NET 统一计划的最后部分。此版本还将对 .NET 整体进行重大改进&#xff0c;包括针对云、桌面和移动应用程序的改进。.NET 6 计划于2021年11月正式发布&…

vba cad 获取宏的路径_VBA批量创建文件目录及链接,建议收藏备用

小伙伴们&#xff0c;之前有跟大家分享过Power Query获取文件夹内文件清单及其属性的方法【Excel快速获取文件列表及文件属性】。今天教大家通过VBA代码来实现同样的功能&#xff0c;提取文件夹内的文件信息更加灵活&#xff0c;只要选择对应的文件夹即可。实现效果操作方法&am…

机器信息MachineInfo

不管是业务功能需要还是开发诊断需要&#xff0c;经常需要用到CPU内存硬盘等信息&#xff0c;或者需要主板编号和系统编号做唯一设备标识。于是设计了机器信息类 MachineInfo &#xff0c;支持Windows、Linux、Raspberry等。Nuget包&#xff1a;NewLife.Core源码地址&#xff1…

学习 Python 编程的 19 个资源

编译&#xff1a;wzhvictor&#xff0c;英文&#xff1a;codecondo segmentfault.com/a/1190000004187319用Python编写代码一点都不难&#xff0c;事实上它一直被赞誉为最容易学的编程语言。如果你准备学习web开发&#xff0c; Python是一个不错的开始&#xff0c;甚至想做游戏…

1155低功耗cpu排行_比拼浮点运算速度,超算排行榜是这样“算”出来的

本报记者 过国忠 通 讯 员 梅国英 吴 婷6月17日&#xff0c;新一期全球超算500强榜单出炉&#xff0c;入选500强的所有超算浮点运算速度都突破每秒千万亿次&#xff0c;中国超算也在前四占有两席位置。普通计算机用指令运算速度衡量计算性能&#xff0c;而超算通常用浮点运算速…