动态规划问题的一般解决方案

动态规划的历史渊源

动态规划问题是由Bellman教授提出的一种用于解决当问题的规模很大时利用转移而将问题分割为子问题的一种算法思想。他也在1979年获得了ACM,IEEE协会颁发的终生成就奖。

动态规划问题的一般思路

由上面的论述,我们可以知道,动态规划问题是用来解决问题规模很大而大问题可以分割为子问题并且加以解决的一种算法思想, 那么, 我们怎么样解决一个动态规划问题呢?
我们从一个十分常见的问题说起:单源最短路径问题。我们如何求两个点之间的最短路径, 尤其是这两个点之间可能存在很多中路径的情况呢?当然,你可以尝试所有点之间的边,也就是对你手中的图进行DFS遍历,但是,我们知道,这样的路径组合会非常恐怖,为了不重复在DFS遍历的同时你还需要进行回朔操作, 这个算法的时间复杂度将是O(deg(1)*deg(2)….),即指数级的复杂度,对我们来说太复杂了。
但是,我们可以作如下的思考,对于我们要求最短路径的任意结点对u,v,我们从终点v进行逐层递归,在这里,我们设两个点之间的最短距离为w(u,v),两点之间的边用e(u,v)来表示的话那么如果v和a1,a2…..an临接话,w(u,v)=min(w(u,ai)+e(ai,u)),其中i为1-n间的任意一个数,至此,我们便设计好了子问题的模型.
那么有了子问题,下一步的工作就是递归求解了,那么递归求解的上界是什么呢?根据图论中的内容,两个点之间联通的话一定存在不大于|V|-1条边的通路,所以我们的递归上界是n(在第n次递归中检查负环)。
至此,我们便得到了著名的Bellman-ford算法

BELLMAN-FORD(G,w,s)
  INITIALIZE-SINGLE-SOURCE(G,s)
  for i=1 to |G.v|-1
     for each edge(u,v)in G
        RELAX(u,v,w)
  for each edge(u,v)in G//最后一次检查负环是否存在
        if v.d >u.d+w(u,v)
        return false
  return true

RELAX(u,v,w)
if v.d >u.d+w(u,v)//满足条件,则更新
   v.d =u.d+w(u,v)
   v.pre =u //设置v的前驱

所以,我们就得到了动态规划问题的解决方案:
(1)设计子问题序列
(2)找出解决所有子问题和母问题的方案,并得到转移方程
(3)设计递归上界,并对应求解

另一种情况

有的时候,我们不一定能够立刻找到子问题的输入变量,有的时候需要加入更多的子问题来对母问题作更加详细的分割,看下面的一个问题
给定一串音符,一个人可以用10个手指来弹奏他们,但是在不同的两个音符(记为p,q)之间手指记为(i,j)做动作会有一定的难度,记为D(p,i,q,j)那么求解我们的这一串音符弹奏起来的最小难度是多少?
我们首先得假设是,从第i个音符向下递归求解,但是问题是,向下递归求解的前提是我们要知道究竟上一个音符是由哪一个手指弹奏的,这个时候,母问题又被我们划分成了10个方面(正常人会有10个手指),以他们作为现态来求解次态,就可以得到一个接近线性阶数的算法。

结语

总之,动态规划是一则十分重要也十分有效的解决大规模输入的算法设计思想,他可以简化设计者的设计难度并且获得更好的时间与空间复杂度之间的平衡。而如何在动态规划时找到子问题并设计出转移规律已经成为当今算法研究的热点之一。

    原文作者:动态规划
    原文地址: https://blog.csdn.net/aaron_1996/article/details/50302259
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞