This commit is contained in:
krahets
2023-07-03 16:35:29 +08:00
parent cddd644e4e
commit ccb44ea5ef
5 changed files with 91 additions and 85 deletions

View File

@ -2199,7 +2199,7 @@
<h1 id="131">13.1. &nbsp; 初探动态规划<a class="headerlink" href="#131" title="Permanent link">&para;</a></h1>
<p>「动态规划 Dynamic Programming」是一种用于解决复杂问题的优化算法它把一个问题分解为一系列更小的子问题并把子问题的解存储起来以供后续使用从而避免了重复计算提升了解题效率。</p>
<p>在本节中,我们先从一个动态规划经典例题入手,了解动态规划是如何高效地求解问题的</p>
<p>在本节中,我们先从一个动态规划经典例题入手,先给出它的暴力回溯解法,观察其中包含的重叠子问题,再一步步导出更高效的动态规划解法</p>
<div class="admonition question">
<p class="admonition-title">爬楼梯</p>
<p>给定一个共有 <span class="arithmatex">\(n\)</span> 阶的楼梯,你每步可以上 <span class="arithmatex">\(1\)</span> 阶或者 <span class="arithmatex">\(2\)</span> 阶,请问有多少种方案可以爬到楼顶。</p>
@ -2774,6 +2774,12 @@ dp[i] = dp[i-1] + dp[i-2]
</div>
</div>
<p><strong>我们将这种空间优化技巧称为「状态压缩」</strong>。在许多动态规划问题中,当前状态仅与前面有限个状态有关,不必保存所有的历史状态,这时我们可以应用状态压缩,只保留必要的状态,通过“降维”来节省内存空间。</p>
<p>总的看来,子问题分解是一种通用的算法思路,在分治算法、动态规划、回溯算法中各有特点:</p>
<ul>
<li>分治算法将原问题划分为几个独立的子问题,然后递归解决子问题,最后合并子问题的解得到原问题的解。例如,归并排序将长数组不断划分为两个短子数组,再将排序好的子数组合并为排序好的长数组。</li>
<li>动态规划也是将原问题分解为多个子问题,但与分治算法的主要区别是,<strong>动态规划中的子问题往往不是相互独立的</strong>,原问题的解依赖于子问题的解,而子问题的解又依赖于更小的子问题的解。因此,动态规划通常会引入记忆化,保存已经解决的子问题的解,避免重复计算。</li>
<li>回溯算法在尝试和回退中穷举所有可能的解,并通过剪枝避免不必要的搜索分支。原问题的解由一系列决策步骤构成,我们可以将每个决策步骤之后的剩余问题看作为一个子问题。</li>
</ul>