背包问题

以集合的角度思考背包问题

当面对dp问题,首先考虑两个内容:(1)状态表示(2)状态计算

(1)状态表示

  • 集合:f(i)(j) 表示一个集合,这个集合包含不同的选法。
  • 条件:这个集合表示,选前 i 件物品,且总体积不大于 j 的选法。
  • 属性:f(i)(j) 的值代表 max?还是min?还是某个数x的个数?等等...

(2)状态计算

状态计算就是将集合拆分,拆成多个子集合,每个子集合用不同的式子表达。

切分的依据是:“寻找最后一个不同点”

01背包

特点:每件物品只能使用一次。

用集合的角度看待01背包问题:

(1)状态表示:

假设物品共有N件、物品总体积为V。那么 f(i)(j) {0<i<=N,0<j<=V} 表示:

  • 集合:从背包中选前 i 件物品,且物品总体积小于 j 的选法集合。
    例如 f(4)(7) 表示选前4件且总体积不大于7的各种选法。

  • 属性:所有选法对应价值中的最大值。
    例如 f(4)(7) 的各种选法中,哪个价值最大。

(2)状态计算:

通过是否包含第 i 件,将集合 f(i)(j) 拆分成两部分。最终 f(i)(j) = max(集合1,集合2)

  • 集合1:选的物品不包含第 i 件(或者说选前 i - 1 件),且体积不大于 j
    表达式:f(i - 1)(j)

  • 集合2:选的物品包含第 i 件,且体积不大于 j
    难点:如何表示包含第i件? 曲线救国,假设现在已经装有第 i 件,然后把第 i 件拿出,此时背包最大价值为 f(i - 1)(j - V(i) ),然后再将第 i 件装回,则包含第 i 件的背包最大价值为 f(i - 1)(j - V(i) ) + W(i)

最终得出:f(i)(j) = max( f(i - 1)(j), f(i - 1)(j - V(i) ) + W(i) )

优化为一维数组

为什么可以优化?

若将 f(i)(j) 看作二维数组,那么 i 只和 i - 1 有关,即下一行由上一行得出。而 j 也只和上一行的 j 和 j-V(i) 有关,即下一行的每一项,由上一行同位置左侧的值得出。

posted @ 2022-05-21 15:33  moon_orange  阅读(34)  评论(0编辑  收藏  举报