8/2,背包问题
特点一:至少要用目标值作为一个 DP 维度
特点二:对具体元素敏感(比如 01 背包),但对同一 totalSize / totalValue 来讲,有时候如何构造而来的具体路线不重要。这是由元素特性和背包 size 的约束条件决定的,也是有别于其他种类 DP 的一个重要区别。
比如 Combination Sum IV,就是典型的 “对最终结果敏感,对元素个数不敏感” 的问题,每次可以取任意元素,任意个,因此只用 dp[sum] 一个维度做 dp 就够了。
在只取 min/max 的时候我们不同的循环顺序都能保证正确答案;但是求解的数量时,要以 target value 为外循环。

显然,路径个数 = 叶节点个数 = 2^n.
dp[i][sum] = 前 i 个元素里我们能不能凑出来 sum.

dp[i][j] 包里有 j 的空间,可以取前 i 个元素时,所能获得的最大收益。
同时因为每次新迭代循环中, i 是不会走回头路的,所以状态与状态之间可以在不违反题意的情况下衔接起来。
仔细观察一下这题:
这就是背包啊!
然而这个条件会带来一个重要的改变:元素的具体位置和数量都不重要了。我们可以直接扔掉这个维度,就像 Coin Change 和 Combination Sum IV 一样。
因此可以看到,只有对元素的选择(位置) / (数量)有限制性条件的 DP,才会需要另一个维度。
注意这里内外循环的顺序不能错,要先按 sum 从小到大的顺序看,然后才是遍历每个元素。因为所谓 bottom-up,是相对于 sum 而言的,不是相对于已有元素的 index 而言的。
可以看到,在只取 min/max 的时候我们不同的循环顺序都能保证正确答案;但是求解的数量时,要以 target value 为外循环。
我们关注的维度有三个:
时间:O(len * k * target),三重循环
空间:O(k * target)
Last updated