动态规划只是用更简单的子问题来定义问题。
就斐波那契数列而言,我们用两个较小的项来定义问题。
在这种情况下,我们根据包含较少项目和可能较小容量的子问题来定义具有一定数量项目和一定容量的问题。
我们首先计算最多 1 个项目和每个容量的利润。然后我们计算最多 2 个项目和每个容量的利润。然后我们最多对 3 个项目执行此操作,然后是 4 个,依此类推。由于我们已经根据具有较少项目的子问题定义了一个问题,因此我们可以简单地查找我们已经计算的内容来确定具有 2、3、4 等项目的任何值。
将其视为物理 2D 网格可能会有所帮助,您可以在其中从一个方向到另一个方向填充值,并且每次您只查看所有值已填充的方向。
存在重叠的子问题,因为在一种情况下我们使用相同的容量,而在另一种情况下我们使用较小的容量。较小的容量有时会匹配检查相同容量的不同子问题。也就是说f(i+1, j)
因为一个问题将等于f(i+1, y - w_i)
对于另一个问题。作为示例,您可以看到f(11, 5)
出现在2个地方:
f(10, 8) = max(f(11, 8), f(11, 5) + 77) // w_i = 3
f(10, 5) = max(f(11, 5), f(11, 2) + 77)
在这种情况下我们已经计算过f(11, X)
对于每一个X
,所以我们可以查找这些值。
我确实觉得我们用增加来定义问题有点令人困惑i
, as in f(i, j) = ...f(i+1, X)...
然后f(n, X)
因此最多包含 1 项,而不是使用递减i
并且最多有 1 件物品f(1, X)
。但这只是语义,并不能以任何方式改变问题。
技术细节说明
f(i,y)
是包含项目子集的最大利润i
通过n
容量为y
.
现在我们可以将其定义为包含或排除项目i
,然后获得物品的最大利润i+1
通过n
.
当我们排除项目时i
,这不会改变重量,所以我们可以只看相同容量下的最大利润,即f(i+1, y)
,利润也不变。
当我们包括项目时i
,这会改变重量,特别是物品的重量i
,即w_i
,所以我们必须查找f(i+1, y - w_i)
。但我们也从 item 中获得利润i
,所以我们需要加上它的利润,即p_i
.
现在,由于我们想要最大利润,我们必须找到这两个值的最大值,给出:
f(i, y) = max{f(i+1, j), f(i+1, y - w_i) + p_i}
如果您仍然无法理解它,我建议您为自己构建一个示例来完成 - 没有多少解释足以看到它实际工作,并使用它来获得一些直觉,了解为什么我们这样做。