深度学习速通系列:动态规划算法

动态规划(Dynamic Programming,简称DP)是一种算法策略,用于解决具有重叠子问题和最优子结构特性的优化问题。它是一种将复杂问题分解成更简单的子问题,并通过存储这些子问题的解(通常在一个表格中),避免重复计算,从而提高效率的方法。

动态规划的原理:

  1. 重叠子问题:动态规划适用于那些子问题会重复出现的问题。每次遇到子问题时,都计算其解并将其存储起来,之后再次遇到时直接使用。

  2. 最优子结构:一个问题的最优解包含其子问题的最优解。这意味着可以通过子问题的最优解来构建原问题的最优解。

  3. 无后效性:一旦某个状态被确定,它就不受之后决策的影响。这意味着你可以在不担心未来决策的情况下,独立地解决每个子问题。

  4. 记忆化:动态规划通常涉及两个过程,自顶向下的“记忆化”递归和自底向上的迭代。在记忆化递归中,每次解决子问题时都会检查是否已经计算过该子问题的解;如果是,则直接使用存储的解。

动态规划的基本步骤:

  1. 定义状态:确定dp数组的含义,每个元素dp[i]通常代表一个子问题的解。

  2. 确定状态转移方程:找出状态之间的关系,即如何从已知状态得到新状态。

  3. 确定初始状态和边界条件:初始化dp数组,确定算法的起点。

  4. 确定计算顺序:确定如何计算dp数组,通常采用自底向上的方法。

例子:0/1背包问题

问题描述
假设你有一个背包,它能承载的最大重量为W。现在有n个物品,每个物品有一定的重量wi和价值vi,你需要选择一些物品装入背包,使得背包中物品的总价值最大,但总重量不超过W。

动态规划解法

  1. 定义状态dp[i][j]表示在前i个物品中,背包容量为j时的最大价值。

  2. 状态转移方程

    • 如果不选择第i个物品:dp[i][j] = dp[i-1][j]
    • 如果选择第i个物品(前提是j >= wi):dp[i][j] = dp[i-1][j-wi] + vi
    • 综合两种情况:dp[i][j] = max(dp[i-1][j], dp[i-1][j-wi] + vi)
  3. 初始状态dp[0][j] = 0 对所有j,因为没有物品时价值为0。

  4. 边界条件dp[i][0] = 0 对所有i,因为背包容量为0时无法装任何物品。

  5. 计算顺序:按照i和j从小到大的顺序计算。

Python代码实现

def knapSack(W, wt, val, n):
    dp = [[0 for x in range(W+1)] for x in range(n+1)]

    for i in range(1, n+1):
        for w in range(1, W+1):
            if wt[i-1] <= w:
                dp[i][w] = max(val[i-1] + dp[i-1][w-wt[i-1]], dp[i-1][w])
            else:
                dp[i][w] = dp[i-1][w]
    return dp[n][W]

# 物品重量
wt = [1, 3, 4, 5]
# 物品价值
val = [1, 4, 5, 7]
# 背包最大承载重量
W = 7
# 物品数量
n = len(wt)

print(knapSack(W, wt, val, n))

在这个例子中,我们使用了一个二维数组来存储子问题的解,并通过填充这个数组来找到最大价值。动态规划使我们避免了重复计算子问题的解,从而提高了算法的效率。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ven%

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值