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

原创 2018年01月03日 00:00:00



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


旅行商问题,即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在多项式时间内的解法目前还没出现,但我相信未来一定会诞生。


动态规划与递推——动态规划是最优化算法 ( 转自2004chen)

动态规划与递推——动态规划是最优化算法   2008-02-10 17:07:19|  分类: 默认分类 |举报|字号 订阅动态规划的实质是分治和解决冗余,因此动态规划也是递归思想的应用之一。但是,...
  • Songjs19931206
  • Songjs19931206
  • 2015年01月04日 14:32
  • 1300

动态规划(2):动态规划的三种形式

例:数字三角形(POJ 1163)Language:DefaultThe TriangleTime Limit: 1000MSMemory Limit: 10000KTotal Submissions...
  • sun897949163
  • sun897949163
  • 2016年07月31日 11:41
  • 872

归纳与递推

归纳与递推         先来看一个超级简单的例题:     有5人坐在一起,当问第5个人多少岁,他说比第4个人大2岁,问第4个人多少岁,他说比第3个人大2岁,依此下去,问第一个人多少岁,他说他...
  • ZLambert
  • ZLambert
  • 2017年03月24日 22:53
  • 336

2014-11-20动态规划:顺推法与逆推法中递推公式的不同!

1、动态规划的基本概念有哪些? 阶段、(阶段)状态、状态变量si、状态集Si、决策、决策变量ui(si)、决策集Di(si)、状态转移方程、决策的指标函数、策略的指标函数、最优值函数等。 2、什么...
  • Songjs19931206
  • Songjs19931206
  • 2014年12月25日 19:38
  • 1821

递归与递推 & 动态规划、递推、贪心和搜索

递推与递归: 1,从程序上看,递归表现为自己调用自己,递推则没有这样的形式。 2,递归是从问题的最终目标出发,逐渐将复杂问题化为简单问题,最终求得问题 是逆向的。递推是从简单问题出发,一步步的向前发展...
  • KinboSong
  • KinboSong
  • 2017年03月27日 18:58
  • 311

递推计数问题题目总结

introduction主要总结一些常用的递推计数技巧和题目.包括格点计数.树堆排列数目.分类技巧分类是处理计数问题的重要计数.一定要注意不重不漏.并且常对包含某一个元素的特定情况进行计数,然后在全部...
  • Dylan_Frank
  • Dylan_Frank
  • 2017年03月27日 22:14
  • 519

CodeForce 706C 动态规划 利用下标表示状态 递推 (伪状态压缩)

好吧,在比赛的时候最后20分钟才看这道题目,当时的想法是既然数据量有100000,而且又只给1000ms,那么应该是O(n)的算法了,当时就想到了利用递推。。。可是没有去写,也许是没有仔细的考虑清楚吧...
  • Good_night_Sion_
  • Good_night_Sion_
  • 2016年08月13日 15:59
  • 328

动态规划:从新手到专家(一)

动态规划:从新手到专家(一)
  • mimi9919
  • mimi9919
  • 2016年04月25日 23:41
  • 4250

几道动态规划(递推)的题

几道动态规划(递推)的题这些动态规划都是同一种方法,利用递推依次求解最优项。 P1259 饥饿的奶牛 P1258 公交乘车 P1257 轮船问题 P1251 圆上不相交弦 描述 Descriptio...
  • NathanielNIu
  • NathanielNIu
  • 2017年07月30日 11:02
  • 224

加了限制条件的动态规划

动态规划有时候会加各种限制条件,但其实总的套路是不变的,只需要在其中加一些条件,并可能需要进行数据的预处理。 题目:购物单问题=====================================...
  • skyinmoon
  • skyinmoon
  • 2017年05月14日 16:52
  • 337
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:递推与储存,是动态规划的关键
举报原因:
原因补充:

(最多只允许输入30个字)