不同类型的背包问题(如0-1背包、完全背包、多重背包等)对DP数组的初始化方法有不同的需求,主要从dp[0],dp[j]两个角度,求最大值or最小值考虑。以下是一些常见背包问题的DP初始化方法:
1. 0-1背包问题
- 目标:每种物品只能选择0个或1个,尝试在不超过背包容量的前提下最大化总价值。
- 初始化:
dp[0] = 0
:不放入任何物品时,总价值为0。dp[j]
(对于所有正数j)初始化为0,因为初始时没有任何物品可以被放入背包。
2. 完全背包问题
- 目标:每种物品可以无限次选择,尝试在不超过背包容量的前提下最大化总价值。
- 初始化:
dp[0] = 0
:不放入任何物品时,总价值为0。dp[j]
(对于所有正数j)通常初始化为0,因为每种物品可以无限使用,理论上总是能够凑齐任意小于等于容量的总重。
3. 最小化硬币问题(如Piggy-Bank)
- 目标:使用尽可能少的货币价值来恰好凑齐特定的重量。
- 初始化:
dp[0] = 0
:总重为0时,不需要任何硬币。dp[j]
(对于所有正数j)初始化为一个大数(如无穷大inf=1e9+7
),表示一开始认为凑齐这个重量是不可能的。
4. 多重背包问题
- 目标:每种物品有限定的数量,尝试在不超过背包容量的前提下最大化总价值。
- 初始化:
dp[0] = 0
:不放入任何物品时,总价值为0。dp[j]
(对于所有正数j)通常初始化为0,这是因为没有物品可以放入背包。
初始化的选择影响
- 求最大值问题:通常将除
dp[0]
之外的所有值初始化为一个极小值(如0或负无穷),因为要从所有可能中选择最大的。 - 求最小值问题:通常将除
dp[0]
之外的所有值初始化为一个极大值(如正无穷),因为要从所有可能中选择最小的。
不同问题的初始化策略不同,这主要取决于我们的目标是最大化还是最小化以及问题的具体约束条件。正确的初始化对于确保动态规划解的正确性和效率至关重要。
why经常取inf=1e9+7?
在动态规划中选择inf
作为一个非常大的数(如1e9+7
),是为了确保在进行比较和计算过程中,任何初始值或非可达值都被视为一个极端情况,使得算法能够正确地选择合理的最优解。对于1e9+7
这个特定值的选择有几个考虑因素:
1. 充分大
这个值足够大,可以确保在绝大多数实际问题中,任何合理的数值都远小于1e9+7
。这保证了在初值设置为inf
的情况下,任何通过实际步骤得到的数值都会小于inf
,因此能被正常更新。
2. 常见的大数
1e9+7
不仅仅是一个大数,它也是一个常用的质数,经常在算法竞赛和某些哈希计算中使用。它的使用在编程中已经较为普遍,部分原因是因为它与常用的32位整数的上限(2^31-1
,即约21亿)相比,较小且安全。
3. 避免溢出
选择一个如1e9+7
这样的数作为inf
,还有一个实际的考虑是避免在进行整数运算(尤其是加法和乘法)时发生溢出。由于1e9+7
远小于32位整型的最大值,它在多数情况下可以安全地用于计算,不会导致整数溢出。
4. 对比其他大数
相对于选择更大的数如1e18
(可能在某些语言或情况下导致溢出),1e9+7
是一个在效率和安全性之间很好的折衷,尤其是在不涉及大数库的语境下。
总结来说,选择1e9+7
作为inf
的值是因为它足够大,以确保在比较操作中,任何可能的有效计算结果都会被考虑,同时也足够安全,不会在常见的整数运算中引起溢出。这使得1e9+7
成为动态规划和其他算法中一个理想的哨兵值。