返回
01 背包问题:揭开动态规划的奇妙奥秘
后端
2023-10-05 00:33:30
01 背包问题,一个听起来朴实无华的问题,却蕴含着计算机科学中至关重要的动态规划思想。它不仅是众多算法竞赛和编程面试的宠儿,更是实际生活中优化决策的利器。
01 背包问题概述
01 背包问题如下:
有 n 件物品和一个最多能背重量为 w 的背包。每件物品的重量是 weight[i],得到的价值是 value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。
为了解决这个问题,我们首先需要明确目标:在背包容量的限制下,如何选择物品,才能使装入背包的物品总价值最大。
动态规划的闪亮登场
动态规划(Dynamic Programming)是一种解决优化问题的强大方法。它通过将问题分解成一系列重叠子问题,并逐个解决这些子问题,最终得到问题的整体解决方案。
在 01 背包问题中,我们可以定义子问题为:对于背包容量为 j,物品集合为 S,如何选择物品装入背包,才能使装入背包的物品总价值最大?
解决子问题的过程,本质上就是枚举物品,并根据物品的重量和价值,决定是否将其装入背包。具体而言,我们可以使用如下状态转移方程:
f(j, S) = max{f(j, S - {i}), f(j - weight[i], S - {i}) + value[i]}
其中:
- f(j, S) 表示背包容量为 j,物品集合为 S 时,装入背包的物品总价值最大值。
- f(j, S - {i}) 表示背包容量为 j,物品集合为 S 去掉物品 i 时,装入背包的物品总价值最大值。
- f(j - weight[i], S - {i}) + value[i] 表示背包容量为 j - weight[i],物品集合为 S 去掉物品 i 时,装入背包的物品总价值最大值,加上物品 i 的价值。
通过不断地计算子问题,最终可以得到整体问题的最优解。
Python 实现
def knapsack(weight, value, capacity):
n = len(weight)
dp = [[0] * (capacity + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
for j in range(1, capacity + 1):
if weight[i - 1] > j:
dp[i][j] = dp[i - 1][j]
else:
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i - 1]] + value[i - 1])
return dp[n][capacity]
if __name__ == "__main__":
weight = [1, 3, 4, 5]
value = [1, 4, 5, 7]
capacity = 7
max_value = knapsack(weight, value, capacity)
print(max_value)
结语
01 背包问题是一个经典的动态规划问题,它不仅是算法竞赛和编程面试的常见题目,也是实际生活中优化决策的利器。通过深入理解 01 背包问题的解题思路和算法实现,我们可以掌握动态规划的精髓,并将其应用到更广泛的问题中。