算法基础:动态规划

本博客所有内容均整理自《算法图解》,欢迎讨论交流~

动态规划是一种很优雅的算法,它可以认为是使用了分治法的思想,即将大问题划分成小问题,逐一击破这些小问题,从而总体上解决大问题

对于动态规划的定义,百度百科是这样给出的:动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法。20世纪50年代初美国数学家R.E.Bellman等人在研究多阶段决策过程(multistep decision process)的优化问题时,提出了著名的最优化原理(principle of optimality),把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解,创立了解决这类过程优化问题的新方法——动态规划。

动态规划一般用于解决非常棘手的问题,因为如果不棘手,我们就直接解决了,就不需要划分成小问题了。

实话实说,动态规划学起来很难,因为非常抽象。这里我引用《算法图解》书中的一个贯穿始终的例子来解析动态规划。


1、背包问题

假设你是一个小偷,背着一个可装4磅重量东西的背包去偷东西。你可盗窃的商品有如下三件:

 

为了让盗窃的商品价值最高,你该选择盗窃哪些商品呢?

第一种思路:简单暴力

对于上面这个问题,我们很容易就能想到一种解决办法,那就是穷举法。我们尝试各种可能的组合,判断是否能够装得下背包,然后在能够装得下的所有组合中选择价值最高的那一种,搞定!

所有可能的组合如下图所示:

 

不难看出,选择偷吉他+笔记本电脑的组合是最优的。这种办法可行,但是速度非常慢,而且不具有普适性。

在有3件商品的情况下,你需要计算8个不同的集合,而有4件商品时,你需要计算16种组合,当有n个商品时,你需要计算2^{n}种组合。所以这种办法的运行时间为O(2^{n})。

很明显,这不是一个可以让人信服的办法。只要商品数量多到一定程度,这种算法虽然一定有解,但行不通,因为世上没有长生不老药。

所以,我们希望通过一种近似算法快速获取该问题的近似解,虽然不一定是最优解,但很接近,而且速度快。

于是,动态规划的优越性就显现了出来。

第二种思路:近似算法——动态规划

上面说过,动态规划先解决子问题,再逐步解决大问题。

对于背包问题,你先解决小背包(子背包)问题,再逐步解决原来的问题。就像下面这张图表现的那样:

 

我们需要解决一个4磅背包的问题,那我们就首先解决3磅背包和1磅背包的问题,二者解决完之后合起来,就相当于解决了整个的4磅背包问题。

对于具体的解决步骤,我们一步一步地来。

每个动态规划算法都从一个网格开始,背包问题的网格如下:

 

网格的各行为商品,各列为不同容量的背包,1~4磅。所有这些列你都需要,因为它们将帮助你计算子背包的价值。

网格最初是空的。你将填充其中的每个单元格,网格填满后,就找到了问题的答案!我们接下来就一步一步地填写该网格。

1.吉他行

首先来看第一行,这是吉他行,意味着你将尝试把吉他装入背包。

在每个单元格中,都需要做一个简单的决定:偷不偷吉他?做决定的依据就是,你要找出一个价值最高的商品集合。

第一个单元格表示背包的容量为1磅。吉他的重量也是1磅,这意味着它能够装入背包。因此最高单元格可以包含吉他,价值为1500美元。所以单元格填写如下:

 

与这个单元格一样,每个单元格都将包含当前可装入背包的所有商品。

来看下一个单元格,这个单元格表示背包的容量为2磅,很明显,1磅的时候都足以装下吉他,2磅的时候就更可以了!

所以,单元格填写如下:

 

依此类推,这一行的其他单元格也一样填写。别忘了,这才是第一行,只有吉他可供选择,也就是说此时假设你还没法盗窃其他商品。所以第一行结束时,网格填写如下:

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值