本章是个很有趣的问题,也是难倒很多人的问题,同时这又是个会而不难的问题。
动态规划的核心逻辑是:将问题分解为子问题。在《算法图解》这本书里,深入浅出得讲了递推公式的推演逻辑,但是在关键部分,递推公式部分,并没给出逻辑。
整个过程好像是,前面一段道路很平缓,走起来很舒适,但是突然一个大台阶挡住了去路,本篇将试图为这个台阶做一下铺垫,让这个过程更加容易理解一些。
主体仍然以书上的例子作为演示素材。
问题定义
背包问题场景之一,可以盗窃的东西如下:
现在你的背包容量只有4磅,目标是在容量允许的情况下,偷到最有价值的物品组合。
最直接的想法是遍历,三个物品,每个物品都有被偷和不被偷的2种选择,所以总共有 2 3 = 8 2^3 = 8 23=8种选择。
如果有 n n n个物品,那么问题的规模就变成了 2 n 2^n 2n次方,显然这是不可接受的算法。
现在看看用动态规划如何解决。
动态规划
现在把问题拆解为两个方向:
- 增多物品选择
- 增大背包空间
所以这是两个维度的扩展,我们用一个二维的表格来跟踪问题的解决方案。
每个动态规划算法都从一个表格开始。
行为物品种类,列为背包容量大小。
那么在第一行的时候,意味着我们只能选择吉他,吉他的重量是1磅,价值是1500美元。
所以在背包容量为1时,最大价值是1500美元,容量为2,3,4时都是1500美元,因为此时只有一个选择。
所以第一行填满了:
现在我们扩大物品选择选项,即音响也可以纳入选择了。我们此时来填第二行。
这里我们即可以讲讲填充时的指导规则,而不是自己在脑海里遍历。。我们对选项不多的问题,天然有遍历的倾向,然后问题扩大时,又因为没有指导规则,就会手足无措。
现在有音响了,意味着我们可以选择两个物品:
- 吉他:重1磅,价值1500美金
- 音响:重4磅,价值3000美金
我们现在来填第二行第一格。我们可以这么想,我们到底有多少选择呢?
其中背包空间是1磅重,其实我们就两个选择:
- 不选择音响
- 选择音响
如果不选择音响的话,我们就可以不看第二行了,直接把条件再综合一下:
- 不选择音响(只有吉他可选)
- 背包大小为1
能够偷到的价值是不是和第一行第一列的数值1500美元一样?
是的。但这只是第一个选择。如果是第二个选择呢?我们确定要选择音响,但是一算,音响重4磅,装不下,所以最终答案就只能是1500美元。
这个逻辑理解的话,我们可以直接上递推公式了:
c e l l [ i ] [ j ] = m a x { c e l l [ i − 1 ] [ j ] , 当 前 商 品 价 值 + 剩 余 空 间 最 大 价 值 cell[i][j] =max{ \begin{cases} cell[i-1][j], \\ 当前商品价值 + 剩余空间最大价值 \end{cases} } cell[i][j]=max{ cell[i−1][j],当前商品价值