动态规划DP 导言

1,什么是DP

动态规划(Dynamic Programming      简称DP)是一种解决多阶段决策问题的数学优化方法。它通过将复杂问题划分为若干个子问题,并采用递推的方式求解子问题,最终得到原问题的最优解

动态规划的核心思想是利用已经解决过的子问题的解来求解当前问题,以减少计算量。具体而言,动态规划通常包括以下几个步骤:

  1. 定义状态:将原问题划分为若干个子问题,并定义状态表示问题的子解。
  2. 建立状态转移方程:根据子问题之间的关系,建立状态转移方程,描述状态之间的演变关系。
  3. 确定初始状态:确定初始状态的值或者边界条件。
  4. 利用状态转移方程进行递推:根据状态转移方程,从初始状态开始,逐步计算出所有的状态值。
  5. 根据需要得到最优解:根据已经计算得到的状态值,可以得到最优解的具体内容。

动态规划广泛应用于各种问题,例如最短路径问题、背包问题、序列比对等。它的优势在于能够将复杂问题拆分为简单的子问题,并且通过存储已解决的子问题的解来避免重复计算,从而提高运算效率。

2,DP解题步骤

状态转移公式(递推公式)是很重要,但动规不仅仅只有递推公式。

DP五部曲

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

注意的是:一些情况是递推公式决定了dp数组要如何初始化。

dp 也是 记忆化搜索 之一,例如:Fbn 数列,就是记录好我们计算过的子问题,避免多次重复计算。

最后,写的过程中可以  debugv(dp)即 打印一遍 dp数组

查看 dp 数组是否符合自己想要的效果。

### 动态规划DP介绍 动态规划(Dynamic Programming,DP)是一种解决复杂问题的算法设计技术,由理查德·贝尔曼在20世纪50年代提出,不仅为最优控制、强化学习等领域奠定了理论基础,而且在经济学、工程学等众多领域广泛应用。它通常用于优化问题,通过将问题分解为子问题并使用子问题的解来构建整体解决方案[^1][^3]。 ### 动态规划DP原理 动态规划的核心思想是将原问题分解为相互重叠的子问题,并使用递归或迭代的方式求解子问题,然后将子问题的解组合起来得到原问题的解。与递归算法不同的是,动态规划会将子问题的解保存起来,避免重复计算,从而提高效率。其基本数学工具是贝尔曼方程,通过它可以利用递归思想来求解每个子问题[^1][^3]。 ### 动态规划DP应用 动态规划在很多领域都有应用,在现代控制理论、运筹学、人工智能、经济学、工程学等领域,它是求解多阶段决策问题的重要方法。还适用于解决带限制条件的DP问题,如连续型资源约束(重量、体积、时间)的问题[^3][^4]。 ### 动态规划DP案例 #### 斐波那契数列 斐波那契数列是一个经典的动态规划案例,数列定义为:$F(0)=0$,$F(1)=1$, $F(n)=F(n - 1)+F(n - 2)$($n ≥ 2$,$n ∈ N*$)。 ```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] print(fibonacci(10)) ``` #### 背包问题 背包问题是另一个经典的动态规划问题,给定一组物品,每个物品有自己的重量和价值,在限定的总重量内,选择其中若干个物品,使得所选物品的总价值最大。 ```python def knapsack(weights, values, capacity): n = len(weights) dp = [[0 for _ in range(capacity + 1)] for _ in range(n + 1)] for i in range(1, n + 1): for w in range(1, capacity + 1): if weights[i - 1] <= w: dp[i][w] = max(values[i - 1] + dp[i - 1][w - weights[i - 1]], dp[i - 1][w]) else: dp[i][w] = dp[i - 1][w] return dp[n][capacity] weights = [2, 3, 4, 5] values = [3, 4, 5, 6] capacity = 8 print(knapsack(weights, values, capacity)) ``` #### 最长公共子序列(LCS) 给定两个序列,找出它们的最长公共子序列的长度。 ```python def longest_common_subsequence(text1, text2): m = len(text1) n = len(text2) dp = [[0 for _ in range(n + 1)] for _ in range(m + 1)] for i in range(1, m + 1): for j in range(1, n + 1): if text1[i - 1] == text2[j - 1]: dp[i][j] = dp[i - 1][j - 1] + 1 else: dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) return dp[m][n] text1 = "abcde" text2 = "ace" print(longest_common_subsequence(text1, text2)) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值