动态规划 (Dynamic Programming, 简称DP) 是一种解决复杂问题的方法,它通过将问题分解为更简单的子问题来解冔。让我们用DP解决一个非常经典的问题:斐波那契数列。
斐波那契数列的定义如下:
scssCopy code
F(0) = 0
F(1) = 1
F(n) = F(n-1) + F(n-2) 对于 n > 1
传统递归方法的实现:
pythonCopy code
def fibonacci_recursive(n):
if n <= 1:
return n
else:
return fibonacci_recursive(n-1) + fibonacci_recursive(n-2)
但是这种方法的效率非常低,因为它会多次计算相同的子问题。
现在,我们使用动态规划方法来优化它:
pythonCopy code
def fibonacci_dp(n):
if n <= 1:
return n
# 初始化存储结果的数组
fib = [0] * (n+1)
fib[1] = 1
# 从下到上计算每一个斐波那契数
for i in range(2, n+1):
fib[i] = fib[i-1] + fib[i-2]
return fib[n]
动态规划版本的优点是,它不会重复计算相同的子问题,因为我们将之前计算的结果存储起来,并直接使用这些结果。这大大提高了计算速度。
用一个例子,说明背包问题
ChatGPT
背包问题是动态规划中的一个经典问题。为了简洁明了,我们先从0-1背包问题开始。
问题描述:
假设你是一个盗贼,准备打劫一个商店。你有一个背包,它的容量有限,而商店里有多种物品,每种物品有一定的重量和价值。由于背包的容量有限,你不能把所有物品都拿走,所以你需要选择一些物品,使得拿走的这些物品的总价值最大。
具体描述:
示例:
假设我们有以下物品:
cssCopy code
物品 重量 价值
A 2 3
B 3 4
C 4 5
D 5 6
背包的最大容量为8。
一个最优解是选择物品A、B和D,总重量为 2+3+5=102+3+5=10 (超出了背包容量),总价值为 3+4+6=133+4+6=13。
动态规划可以帮助我们找到这个最优解。
动态规划解法:
我们可以定义一个数组 ��[�][�]d**p[i][j] 表示前i个物品,背包容量为j时的最大价值。
递推关系为:
cssCopy code
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i])
Python的简单实现:
pythonCopy code
def knapsack(values, weights, W):
n = len(values)
dp = [[0] * (W + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
for j in range(1, 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]
values = [3, 4, 5, 6]
weights = [2, 3, 4, 5]
W = 8
print(knapsack(values, weights, W)) # 输出:13
这样,我们可以得到在背包容量为8时,最大的价值为13。
powered by kaifamiao