12 最优子结构

在上一篇中,我们探讨了动态规划与经典数据结构的结合,分析了如何将动态规划策略结合不同的数据结构来优化算法性能。本篇将深入剖析动态规划的“最优子结构”特性,通过具体实例分析其在实际问题中的应用。我们将为读者提供必要的理论背景,并结合代码示例,让您能更好地理解这一概念。

最优子结构

动态规划的核心思想是利用“最优子结构”。即一个问题的最优解,可以由其子问题的最优解构成。换句话说,如果能够找到子问题的最优解,并将这些解组合起来,就能够得到原问题的最优解。

示例:背包问题

我们以0-1背包问题为例来说明动态规划的最优子结构。在这个问题中,我们有一个背包,其承重限制为 $W$,我们有 $n$ 个物品,每个物品 $i$ 具有重量 $w_i$ 和价值 $v_i$。目标是选取若干物品放入背包,使得它们的总价值最大。

状态定义

首先,我们定义一个状态 $dp[j]$,表示在承重为 $j$ 的情况下的最大价值。

状态转移方程

对于第 $i$ 个物品,状态转移方程可以写为:

$$
dp[j] = \max(dp[j], dp[j - w_i] + v_i) \quad \text{if } j \geq w_i
$$

这个公式表明,对于容量为 $j$ 的背包,我们可以选择不放入第 $i$ 个物品,或者放入该物品(前提是容量允许),从而求取最大的价值。

最优子结构分析

在这个问题中,任意选择的物品集合的最大价值可以通过选择第 $i$ 个物品的决策来推导出来。这说明了,问题的最优解依赖于子问题的最优解,符合最优子结构的定义。

代码实现

以下是使用动态规划解决 0-1 背包问题的 Python 代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def knapsack(weights, values, W):
n = len(weights)
dp = [0] * (W + 1)

for i in range(n):
for j in range(W, weights[i] - 1, -1): # 从后向前遍历
dp[j] = max(dp[j], dp[j - weights[i]] + values[i])

return dp[W]

# 示例
weights = [2, 3, 4, 5]
values = [3, 4, 5, 6]
W = 5
max_value = knapsack(weights, values, W)
print("最大价值为:", max_value)

运行结果

上述代码中,给定物品的重量和价值,我们可以计算在背包容量限制为 $W$ 的情况下,能够获得的最大价值。运行后输出的结果为:

1
最大价值为: 7

结论

通过 0-1 背包问题的实例,我们深入理解了动态规划中“最优子结构”的重要性及其实用性。当面对一些优化问题时,识别子问题的结构,并通过合理的数据结构来存储和计算,可以有效提升算法的效率。在下一篇中,我们将继续探讨高级排序算法中的堆排序,包括其原理与实现,敬请期待!

作者

AI免费学习网(郭震)

发布于

2024-08-11

更新于

2024-08-12

许可协议

分享转发

交流

更多教程加公众号

更多教程加公众号

加入星球获取PDF

加入星球获取PDF

打卡评论