「烤冷面讲算法」系列,每周更新:https://scriptrunz.com/zh-cn/...
「一个干货技术社群」:https://scriptrunz.com/zh-cn/...
01背包问题
假设你是个小偷,背着一个可装 4 磅东西的背包。你可盗窃的商品有如下 3 件:
为了让盗窃的商品价值最高,你该选择哪些商品?
暴力搜索
暴力搜索法会将每种组合都尝试一遍后找到最优解,显而易见这种算法的时间复杂度为O(2^n),只要问题扩大到一定规模,这个算法一定行不通。
动态规划
动态规划先解决子问题,再逐步解决大问题。
对于背包问题,你先解决小背包(子背包)问题,再逐步解决原来的问题。
按照这个思想,我们尝试将背包容量逐步缩小到 4、3、2、1,计算不同容量的背包所能承载的最大价值。进而,我们可以画出来一个表格,列
代表不同容量的背包,行
代表不同种类物品。
1 | 2 | 3 | 4 | |
---|---|---|---|---|
吉他 | ||||
音响 | ||||
笔记本电脑 |
这是一个表格,也是一个行列式,我们将这个行列式命名为 dp,dp[3] [3] 的值就是题解。我们一步步把行列式的值填满,最终行列式被完全填满后,题解自然水落石出。
填满行列式
第一行是吉他行,这意味着我们尝试将吉他装入背包,在每一个单元格都需要做一个决定:要不要把吉他放到背包里。第一个单元格表示背包的容量为 1 磅。吉他的重量也是 1 磅,这意味着它能装入背包!因此这个单元格包含吉他,价值为 ¥1500。
1 | 2 | 3 | 4 | |
---|---|---|---|---|
吉他 | 1500 | |||
音响 | ||||
笔记本电脑 |
到了下一个单元格,它表示背包的容量为 2 磅,完全能够装下吉他!但是我们只有一把吉他,所以总价值还是 ¥1500。同理,容量为 3、4 磅的背包总价值保持 ¥1500 不变。
1 | 2 | 3 | 4 | |
---|---|---|---|---|
吉他 | 1500 | 1500 | 1500 | 1500 |
音响 | ||||
笔记本电脑 |
来到第二行,可偷的商品有吉他和音响。
音响重 4 磅,所以第二行的前三个格子只能选择吉他,价值 ¥1500。到了第 4 个格子,我们就可以选择更贵的音响,总价值 ¥3000。
1 | 2 | 3 | 4 | |
---|---|---|---|---|
吉他 | 1500 | 1500 | 1500 | 1500 |
音响 | 1500 | 1500 | 1500 | 3000 |
笔记本电脑 |
来到第三行,可偷的商品有吉他、音响、笔记本电脑。
笔记本电脑重 3 磅,所以第 3 行的前 2 个格子只能选择吉他,价值 ¥1500。到了第 3 个格子,我们就可以选择更贵的笔记本电脑,总价值 ¥2000。
1 | 2 | 3 | 4 | |
---|---|---|---|---|
吉他 | 1500 | 1500 | 1500 | 1500 |
音响 | 1500 | 1500 | 1500 | 3000 |
笔记本电脑 | 1500 | 1500 | 2000 | ? |
选择了笔记本电脑后,我们还有 1 磅的空间,此时应该选择什么呢?
dp1已经告诉了我们答案:在背包只有 1 磅容量且仅能选择吉他和音响时,其最大价值为 ¥1500,加上笔记本的 ¥2000 总价值为 ¥3500,超过了上一行的最大价值 ¥3000,刷新了最大价值记录,同时也拿到了最终的题解。
我们成功利用动态规划解决了这个问题,我们合并了两个子问题的解来得到更大问题的解!
状态转移方程
"状态转移方程"这个名字听起来很吓人,其实说白了就是用公式来表示我们上面的策略,写出来公式我们才能用代码求解具体问题。
总结来说,选物品的策略有两种:
有了这个公式化的策略,写代码还真就是最简单的一步了~
参考:
1. 《算法图解》
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。