1.
初始化的细节问题
我们看到的求最优解的背包问题题目中,事实上有两种不太相同的问法。有的题目
要求“恰好装满背包”时的最优解,有的题目则并没有要求必须把背包装满。一种区别
这两种问法的实现方法是在初始化的时候有所不同。
如果是第一种问法,要求恰好装满背包,那么在初始化时除了 F [0] 为 0,其它
F [1::V ] 均设为 1,这样就可以保证最终得到的 F [V ] 是一种恰好装满背包的最优解。
如果并没有要求必须把背包装满,而是只希望价格尽量大,初始化时应该将 F [0::V ]
全部设为 0。
这是为什么呢?可以这样理解:初始化的 F 数组事实上就是在没有任何物品可以放
入背包时的合法状态。如果要求背包恰好装满,那么此时只有容量为 0 的背包可以在什
么也不装且价值为 0 的情况下被“恰好装满”,其它容量的背包均没有合法的解,属于
未定义的状态,应该被赋值为 -∞ 了。如果背包并非必须被装满,那么任何容量的背包
都有一个合法解“什么都不装”,这个解的价值为 0,所以初始时状态的值也就全部为 0
了。
这个小技巧完全可以推广到其它类型的背包问题,后面不再对进行状态转移之前的
初始化进行讲解。
2
1.2 基本思路
这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。
用子问题定义状态:即 F [i; v ] 表示前 i 件物品恰放入一个容量为 v 的背包可以获得
的最大价值。则其状态转移方程便是:
F [i; v] = maxfF [i 1; v ]; F [i 1; v Ci ] + Wi
g
这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的。所
以有必要将它详细解释一下:“将前 i 件物品放入容量为 v 的背包中”这个子问题,若
只考虑第 i 件物品的策略(放或不放),那么就可以转化为一个只和前 i 1 件物品相关
的问题。如果不放第 i 件物品,那么问题就转化为“前 i 1 件物品放入容量为 v 的背
包中”,价值为 F [i 1; v ];如果放第 i 件物品,那么问题就转化为“前 i 1 件物品放
入剩下的容量为 v Ci 的背包中”,此时能获得的最大价值就是 F [i 1; v Ci
] 再加上
通过放入第 i 件物品获得的价值 Wi 。