1. 问题描述
0-1背包装满问题拓展自0-1背包问题, 即将约束条件由不超过背包容量改为恰等于背包容量。
2. 解题思路
解题思路与0-1背包问题完全相同, 区别仅在初始化过程中。
0-1背包问题的初始化过程:
(1) 设 N 为物品总数,
W 为背包最大重量, 定义一个规模为 W+1 的一维数组, 初始化为0, 表示初始背包总价值为0。(2) 第一件物品按照不超过背包容量的条件装填。
这里以 N=5,W=10 为例, 初始化结果为,
i wi vi 0 1 2 3 4 5 6 7 8 9 10 1 2 6 0 0 6 6 6 6 6 6 6 6 6 2 2 3 0 0 0 0 0 0 0 0 0 0 0 3 6 5 0 0 0 0 0 0 0 0 0 0 0 4 5 4 0 0 0 0 0 0 0 0 0 0 0 5 4 6 0 0 0 0 0 0 0 0 0 0 0 最终结果为,
i wi vi 0 1 2 3 4 5 6 7 8 9 10 1 2 6 0 0 6 6 6 6 6 6 6 6 6 2 2 3 0 0 6 6 9 9 9 9 9 9 9 3 6 5 0 0 6 6 9 9 9 9 11 11 14 4 5 4 0 0 6 6 9 9 9 10 11 13 14 5 4 6 0 0 6 6 9 9 12 12 15 15 15 0-1背包装满问题的初始化过程:
(1) 设 N 为物品总数,
W 为背包最大重量, 定义一个规模为 W+1 的一维数组, dp[0] 初始化为0, 其余初始化为-INF。(2) 第一件物品仅对恰好装满的情况进行状态更新。
这里以 N=5,W=10 为例, 初始化结果为,
i wi vi 0 1 2 3 4 5 6 7 8 9 10 1 2 6 0 −∞ 6 −∞ −∞ −∞ −∞ −∞ −∞ −∞ −∞ 2 2 3 0 −∞ −∞ −∞ −∞ −∞ −∞ −∞ −∞ −∞ −∞ 3 6 5 0 −∞ −∞ −∞ −∞ −∞ −∞ −∞ −∞ −∞ −∞ 4 5 4 0 −∞ −∞ −∞ −∞ −∞ −∞ −∞ −∞ −∞ −∞ 5 4 6 0 −∞ −∞ −∞ −∞ −∞ −∞ −∞ −∞ −∞ −∞ 最终结果为,
i wi vi 0 1 2 3 4 5 6 7 8 9 10 1 2 6 0 −∞ 6 −∞ −∞ −∞ −∞ −∞ −∞ −∞ −∞ 2 2 3 0 −∞ 6 −∞ 9 −∞ −∞ −∞ −∞ −∞ −∞ 3 6 5 0 −∞ 6 −∞ 9 −∞ 5 −∞ 11 −∞ 14 4 5 4 0 −∞ 6 −∞ 9 4 5 10 11 13 14 5 4 6 0 −∞ 6 −∞ 9 4 12 10 15 13 14 -INF为非法状态, 即无法装满, -INF加上任意整数仍然为-INF。
这样初始化能够保证, 如果子问题的状态是合法的(恰好装满), 才能得到合法的状态;如果子问题状态是非法的, 则当前问题的状态依然非法, 即不存在恰好装满的情况。
3. INF值的设定
INF 不是一个固定值, 其设定视情况而定。
一般, INF 的设定有三个要点:
(1) 保证足够大。INF 用于表示某种非法状态, 正常运算过程中不能出现达到或者超过INF 的情况, 即INF 应足够大。
(2) 初始化方便。常用
memset()
对数组进行初始化或重置,memset()
是以字节形式进行内存操作的。(3) 溢出问题。INF 不是越大越好, INF 过大会产生溢出问题。有时应避免出现溢出问题, 有时则就是要导致溢出问题, 应具体分析。
以32位有符号整型为例, 0x7fffffff是最大值, 其加上任意整数都会出现溢出, 导致结果为负。
在本题中, 应避免溢出问题, 即保证 dp(i−1,j−wi)+vi=INF+vi=INF 。
故, 设定
−∞=0xf0f0f0f0
+∞=07f7f7f7f
Ver 2.0 2017-2-18