一文弄懂动态规划(DP Dynamic Programming)下楼梯,国王和金矿,背包问题,Dijkstra算法

动态规划

参考链接

漫画算法,什么是动态规划?

DP

动态规划是一种分阶段求解决策问题的数学思想

题目一

问:下楼梯问题,有一座高度是10级台阶的楼梯,从下往上走,每跨一步只能向上1级或者2级台阶,请问有多少中走法。

思路

刚才这个题目,你每走一步就有两种走法,暂时不管0级到8级台阶的过程。想要走到10级,必然是从8级或者9级走的。那么问题来了,如果我们以及0到9级台阶的走法有x种,0到8级台阶有Y种,那0到10级台阶就是X+Y。


image
公式就是:
F(10) = F(9)+ F(8)

当只有1级台阶的时候只有一种解法,2级台阶的时候有两种方法。

递推公式就是:
F(1) = 1
F(2) = 2
F(N) = F(N-1)+ F(N-2)

动态规划的三个概念:

  1. 最优子结构
  2. 边界
  3. 状态转移公式
image

当只有1级台阶或2级台阶,我们直接得出结果,无需建华,我们就成F(1)F(2)为边界。
F(N) = F(N-1)+ F(N-2)是阶段与阶段之间的状态转移公式。

求解问题

方法一:递归法

image

但是复杂度很高,因为当中有很多大量的重复计算。复杂度
O(2^N)
。具体分析见开头的链接。
遇到这种情况,我们只需要创建一个哈希表,在python种建立一个字典就好了。把每次不同参数的计算结果存入哈希,当遇到相同参数时,再从哈希表里面取出,就不会重复计算了。

方法二

image

感觉红色箭头少了个参数。

在以上代码中,集合map是一个备忘录。当每次需要计算F(N)的时候,会首先从map中寻找匹配元素。如果map中存在,就直接返回结果,如果map中不存在,就计算出结果,存入备忘录中

image

image

其实不用对F(N)自顶向下做递归运算,可以从下往上算。已知1,2是不是就能求3了。以此类推。
image

image

image

题目二

国王和金矿
问:有一个国家发现了5座金矿,每座金矿的黄金储量不同,需要参与挖掘的工人数也不同。参与挖矿工人的总数是10人。每座金矿要么全挖,要么不挖,不能派出一半人挖取一半金矿。要求用程序求解出,要想得到尽可能多的黄金,应该选择挖取哪几座金矿?

解答

image

最优子结构:
10个人4金矿(第五金矿不挖的时候),10减去挖第五金矿的人数要求然后剩下4金矿(第五金矿挖的时候)。
最终问题:
10个人5金矿的最优选择。
最优子结构和最终问题的关系:
设几个变量便于描述:
N:金矿数量
W:工人人数
G[]:金矿黄金含量
P[]:金矿的用工量
关系:
F(5,10) = Max(F(4,10),F(4,10-P[4])+ G [4])
==> F(N,W) = Max(F(N-1,W),F(N-1,W-P[N-1])+G[N-1])

边界条件:

if N == 1:
    if W>= P[0]:
        return G[0]
    else:
        return 0

总结:


image

和之前一样,有三种实现方式,简单递归,备忘录算法,动态规划。

方法二:简单递归

把状态转移方程式翻译成递归程序,递归的结束的条件就是方程式当中的边界。因为每个状态有两个最优子结构,所以递归的执行流程类似于一颗高度为N的二叉树。方法的时间复杂度是O(2^N)

方法三:备忘录算法

在简单递归的基础上增加一个HashMap备忘录,用来存储中间结果。HashMap的Key是一个包含金矿数N和工人数W的对象,Value是最优选择获得的黄金数。方法的时间复杂度和空间复杂度相同,都等同于备忘录中不同Key的数量。

方法四:动态规划

在这里插入图片描述

image

image

image

image

规律

image

image

image

在这里插入图片描述

However ,当总工人数变成1000人,每个金矿的用工数也相应增加,这时候如何实现最优选择呢?
image

可能你觉得还是之前的动态规划方法。其实是不对的,我们可以来计算一下,
1000工人5个金矿,需要计算1000 * 5 次,需要开辟 1000 单位的空间。
然而我们用之前的简单递归,需要计算2^n次也就是32次,只需要开辟5单位(递归深度的空间)。
所以从上面计算可以知道,动态规划方法的时间和空间都和W成正比,而简单递归却与W无关,当工人数量很多的时候,动态规划反而不如递归。
(我又一个想法,思路来源于Glibc 中的 qsort() 的实现在这个链接的举例分析排序函数板块中,我的思路是这样的,两个算法都可以写在函数实现上,如果当N特别大的时候,可以选择动态规划的方法,而当N不大,而W特别大的时候,且空间有限制,此时就可以让算法退化成简单递归。不知道对不对这个思路,如果哪里考虑的不对的话,请告诉我,万分感谢)

以上就是漫画算法的全部内容。以下是我的补充内容

背包问题 和迪杰特斯拉(Dijkstra算法--求图最短路径)

背包问题

image

如果认真读了上面的过程,看到这个题目是不是觉得和前面矿工和金矿很像是不是。背包问题就是,钱和重量,而前面矿工和金矿问题是,钱和人数的限制。
接下来的思路是算法图解中关于动态规划的讲解,可以参考看一下。


image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

写出正确的动态规划

image

image

在这里插入图片描述

image

image

image

image

image

image

image

image

image

Dijkstra's Algorithm(是求从一点出发的最短路径)

伪代码

Data: G, s, dist[], pred[] and
vSet: set of vertices whose shortest path from s is unknown
Algorithm:
dist[] // array of cost of shortest path from s
pred[] // array of predecessor in shortest path from s
dijkstraSSSP(G,source):
|   Input graph G, source node
|
|    initialise dist[] to all ∞, except dist[source]=0
|    initialise pred[] to all -1
|   vSet=all vertices of G
|   while vSet is not NULL do
|    |  find s in vSet with minimum dist[s]
|    |  for each (s,t,w) in edges(G) do
|    |  relax along (s,t,w)
|    |  end for
|    |  vSet=vSet \ {s}
|    end while

以上伪代码仅供参考作用,喜欢的话,可以研究一下。下面通过一道题目来了解整个过程。


image
  1. 根据伪代码进行初始化:


    image
  2. 根据题目的要求,从node 0开始,遍历与0相连的每条边的权重,更新列表,pred代表是从哪里来的,比如,第二列的0,代表从0来到1。(图中绿色的代表当前遍历的点)
    image
  3. 然后遍历dist中除去0以外的,最小的值,以这个最小值作为起始点,遍历它连的边,更新列表。


    image
  4. 其实就是重复3的动作,先找剩下的最小边,遍历它连的边,更新列表,你可以动手写一下剩下的内容。当dist发生变化时,pred也要相应的发生变化,毕竟你要记录最短路径,当然要记录这个路径是从哪里来的。


    image

算法复杂度分析

每条边都需要遍历一边,O(E)
外循环是遍历所有点,则是O(V)
"find s in vSet with minimum dist[s]" 这段代码
尝试找s in vSet,cost为O(V)
==>overall cost 为O(E+V^2) = O(V^2)
如果用优先队列来实现找最小距离,那么
Overall cost = O(E+VlogV)

附加题

旅行者问题,动态规划详解

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容

  • 在理解动态规划、BFS和DFS一文中,只是初步讲解了一下动态规划,理解的并不到位,这里再加深理解一下。 本文主要参...
    小碧小琳阅读 11,143评论 1 11
  • 先来看一个问题: 有一座高度是10阶的楼梯,从下往上走,每跨一步可以是一级或两级台阶。要求用程序求出一共一共有多少...
    诗意很适宜阅读 3,146评论 2 4
  • 主页君小提示:图文有点长,慢慢看 ———————————— 题目: 有一座高度是10级台阶的楼梯,从下往上走,每跨...
    起个名字真的好难啊哈哈阅读 3,355评论 0 11
  • 今天在网上看到一个讲动态规划的文章,是以01背包为例的,这文章和书上的讲解非常不一样,令我眼前一亮,于是转载一下下...
    ShadowGlint阅读 2,082评论 1 42
  • 进阶班已经进行到第四周了,可是我一篇文章都没有完成,昨天本来想写来,可是事情太多,又不知道写什么,所以就做了个...
    徐伟豪阅读 218评论 5 2