This commit is contained in:
krahets
2023-12-28 17:18:37 +08:00
parent 8d49c46234
commit d1f1473539
67 changed files with 604 additions and 609 deletions

View File

@@ -552,7 +552,7 @@ $$
<p align="center"> 图 14-8 &nbsp; 带约束爬到第 3 阶的方案数量 </p>
在该问题中,如果上一轮是跳 $1$ 阶上来的,那么下一轮就必须跳 $2$ 阶。这意味着,**下一步选择不能由当前状态(当前所在楼梯阶数)独立决定,还和前一个状态(上轮所在楼梯阶数)有关**。
在该问题中,如果上一轮是跳 $1$ 阶上来的,那么下一轮就必须跳 $2$ 阶。这意味着,**下一步选择不能由当前状态(当前所在楼梯阶数)独立决定,还和前一个状态(上轮所在楼梯阶数)有关**。
不难发现,此问题已不满足无后效性,状态转移方程 $dp[i] = dp[i-1] + dp[i-2]$ 也失效了,因为 $dp[i-1]$ 代表本轮跳 $1$ 阶,但其中包含了许多“上一轮是跳 $1$ 阶上来的”方案,而为了满足约束,我们就不能将 $dp[i-1]$ 直接计入 $dp[i]$ 中。

View File

@@ -27,7 +27,7 @@ comments: true
- 问题的目标是找出所有可能的解决方案,而不是找出最优解。
- 问题描述中有明显的排列组合的特征,需要返回具体的多个方案。
如果一个问题满足决策树模型,并具有较为明显的“加分项,我们就可以假设它是一个动态规划问题,并在求解过程中验证它。
如果一个问题满足决策树模型,并具有较为明显的“加分项,我们就可以假设它是一个动态规划问题,并在求解过程中验证它。
## 14.3.2 &nbsp; 问题求解步骤

View File

@@ -646,7 +646,7 @@ $$
观察图 14-3 **指数阶的时间复杂度是“重叠子问题”导致的**。例如 $dp[9]$ 被分解为 $dp[8]$ 和 $dp[7]$ $dp[8]$ 被分解为 $dp[7]$ 和 $dp[6]$ ,两者都包含子问题 $dp[7]$ 。
以此类推,子问题中包含更小的重叠子问题,子子孙孙无穷尽也。绝大部分计算资源都浪费在这些重叠的问题上。
以此类推,子问题中包含更小的重叠子问题,子子孙孙无穷尽也。绝大部分计算资源都浪费在这些重叠的问题上。
## 14.1.2 &nbsp; 方法二:记忆化搜索

View File

@@ -4,9 +4,9 @@ comments: true
# 14.7 &nbsp; 小结
- 动态规划对问题进行分解,并通过存储子问题的解来规避重复计算,提高 计算效率。
- 动态规划对问题进行分解,并通过存储子问题的解来规避重复计算,提高计算效率。
- 不考虑时间的前提下,所有动态规划问题都可以用回溯(暴力搜索)进行求解,但递归树中存在大量的重叠子问题,效率极低。通过引入记忆化列表,可以存储所有计算过的子问题的解,从而保证重叠子问题只被计算一次。
- 记忆化递归是一种从顶至底的递归式解法,而与之对应的动态规划是一种从底至顶的递推式解法,其如同“填写表格”一样。由于当前状态仅依赖某些局部状态,因此我们可以消除 $dp$ 表的一个维度,从而降低空间复杂度。
- 记忆化搜索是一种从顶至底的递归式解法,而与之对应的动态规划是一种从底至顶的递推式解法,其如同“填写表格”一样。由于当前状态仅依赖某些局部状态,因此我们可以消除 $dp$ 表的一个维度,从而降低空间复杂度。
- 子问题分解是一种通用的算法思路,在分治、动态规划、回溯中具有不同的性质。
- 动态规划问题有三大特性:重叠子问题、最优子结构、无后效性。
- 如果原问题的最优解可以从子问题的最优解构建得来,则它就具有最优子结构。