动态规划
什么是动态规划?
动态规划(Dynamic Programming,简称 DP)是一种用于解决优化问题的算法设计技术。它的核心思想是将一个复杂的问题分解为多个重叠的子问题,通过存储和重用子问题的解来避免重复计算,从而提高算法的效率。
动态规划通常适用于以下两类问题:
- 最优化问题:寻找问题的最优解(如最大值、最小值)。
- 计数问题:计算满足某些条件的解的数量。
动态规划的关键在于 状态定义 和 状态转移方程。状态定义描述了问题的子问题,而状态转移方程则描述了如何从子问题的解推导出更大问题的解。
动态规划的基本步骤
- 定义状态:明确问题的子问题,并用变量表示状态。
- 确定状态转移方程:找到状态之间的关系,即如何从子问题的解推导出当前问题的解。
- 初始化:确定初始状态的值。
- 计算顺序:按照一定的顺序计算所有状态的值。
- 返回结果:根据计算出的状态值,返回最终问题的解。
动态规划的经典问题:斐波那契数列
斐波那契数列是一个经典的动态规划问题。斐波那契数列的定义如下:
- F(0) = 0
- F(1) = 1
- F(n) = F(n-1) + F(n-2) (n ≥ 2)
递归解法的问题
如果直接使用递归实现斐波那契数列,会出现大量的重复计算。例如,计算 F(5) 时需要计算 F(4) 和 F(3),而计算 F(4) 时又需要计算 F(3) 和 F(2),导致 F(3) 被重复计算多次。
动态规划解法
通过动态规划,我们可以将子问题的解存储起来,避免重复计算。以下是动态规划的实现:
python
def fibonacci(n):
if n == 0:
return 0
elif n == 1:
return 1
# 初始化状态数组
dp = [0] * (n + 1)
dp[0] = 0
dp[1] = 1
# 计算状态转移
for i in range(2, n + 1):
dp[i] = dp[i - 1] + dp[i - 2]
return dp[n]
输入和输出
- 输入:
n = 5
- 输出:
5
动态规划的优化:空间优化
在上述斐波那契数列的动态规划解法中,我们使用了一个数组来存储所有状态的值。但实际上,我们只需要存储前两个状态的值即可,从而将空间复杂度从 O(n) 降低到 O(1)。
python
def fibonacci_optimized(n):
if n == 0:
return 0
elif n == 1:
return 1
prev1, prev2 = 1, 0
for _ in range(2, n + 1):
current = prev1 + prev2
prev2 = prev1
prev1 = current
return prev1
动态规划的实际应用:背包问题
背包问题是动态规划的经典应用之一。假设你有一个容量为 W 的背包和 n 件物品,每件物品有一个重量和一个价值。你的目标是选择一些物品放入背包,使得背包中物品的总价值最大,且总重量不超过 W。
状态定义
dp[i][j]
表示前 i 件物品中,总重量不超过 j 的最大价值。
状态转移方程
- 如果不选择第 i 件物品:
dp[i][j] = dp[i-1][j]
- 如果选择第 i 件物品:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i])
代码实现
python
def knapsack(W, weights, values):
n = len(weights)
dp = [[0] * (W + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
for j in range(W + 1):
if weights[i - 1] <= j:
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weights[i - 1]] + values[i - 1])
else:
dp[i][j] = dp[i - 1][j]
return dp[n][W]
输入和输出
- 输入:
W = 10, weights = [2, 3, 4, 5], values = [3, 4, 5, 6]
- 输出:
11
总结
动态规划是一种强大的算法设计技术,适用于解决具有重叠子问题和最优子结构性质的问题。通过定义状态、确定状态转移方程并优化计算顺序,我们可以高效地解决许多复杂问题。
提示
动态规划的关键在于找到合适的状态定义和状态转移方程。多练习经典问题(如斐波那契数列、背包问题、最长公共子序列等)可以帮助你更好地掌握这一技术。
附加资源与练习
-
练习:
- 尝试解决 LeetCode 上的动态规划问题。
- 实现最长公共子序列(LCS)问题的动态规划解法。
-
推荐阅读:
- 《算法导论》中的动态规划章节。
- 动态规划入门指南。