跳到主要内容

动态规划

什么是动态规划?

动态规划(Dynamic Programming,简称 DP)是一种用于解决优化问题的算法设计技术。它的核心思想是将一个复杂的问题分解为多个重叠的子问题,通过存储和重用子问题的解来避免重复计算,从而提高算法的效率。

动态规划通常适用于以下两类问题:

  1. 最优化问题:寻找问题的最优解(如最大值、最小值)。
  2. 计数问题:计算满足某些条件的解的数量。

动态规划的关键在于 状态定义状态转移方程。状态定义描述了问题的子问题,而状态转移方程则描述了如何从子问题的解推导出更大问题的解。


动态规划的基本步骤

  1. 定义状态:明确问题的子问题,并用变量表示状态。
  2. 确定状态转移方程:找到状态之间的关系,即如何从子问题的解推导出当前问题的解。
  3. 初始化:确定初始状态的值。
  4. 计算顺序:按照一定的顺序计算所有状态的值。
  5. 返回结果:根据计算出的状态值,返回最终问题的解。

动态规划的经典问题:斐波那契数列

斐波那契数列是一个经典的动态规划问题。斐波那契数列的定义如下:

  • 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

总结

动态规划是一种强大的算法设计技术,适用于解决具有重叠子问题和最优子结构性质的问题。通过定义状态、确定状态转移方程并优化计算顺序,我们可以高效地解决许多复杂问题。

提示

动态规划的关键在于找到合适的状态定义和状态转移方程。多练习经典问题(如斐波那契数列、背包问题、最长公共子序列等)可以帮助你更好地掌握这一技术。


附加资源与练习

  1. 练习

  2. 推荐阅读