This commit is contained in:
krahets
2023-07-16 04:19:01 +08:00
parent 54b99d13c8
commit dbf682ebc9
110 changed files with 25308 additions and 10305 deletions

View File

@@ -25,7 +25,7 @@
<title>13.2.   DP 问题特性New - Hello 算法</title>
<title>14.2.   DP 问题特性New - Hello 算法</title>
@@ -79,7 +79,7 @@
<div data-md-component="skip">
<a href="#132" class="md-skip">
<a href="#142" class="md-skip">
跳转至
</a>
@@ -113,7 +113,7 @@
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
13.2. &nbsp; DP 问题特性New
14.2. &nbsp; DP 问题特性New
</span>
</div>
@@ -1771,6 +1771,87 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../../chapter_divide_and_conquer/">12. &nbsp; &nbsp; 分治</a>
<label for="__nav_13">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_13">
<span class="md-nav__icon md-icon"></span>
12. &nbsp; &nbsp; 分治
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_divide_and_conquer/divide_and_conquer/" class="md-nav__link">
12.1. &nbsp; 分治算法New
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_divide_and_conquer/build_binary_tree/" class="md-nav__link">
12.2. &nbsp; 构建树问题New
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_14" >
@@ -1782,18 +1863,18 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../../chapter_backtracking/">12. &nbsp; &nbsp; 回溯</a>
<a href="../../chapter_backtracking/">13. &nbsp; &nbsp; 回溯</a>
<label for="__nav_13">
<label for="__nav_14">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_13">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_14_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_14">
<span class="md-nav__icon md-icon"></span>
12. &nbsp; &nbsp; 回溯
13. &nbsp; &nbsp; 回溯
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -1806,7 +1887,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/backtracking_algorithm/" class="md-nav__link">
12.1. &nbsp; 回溯算法
13.1. &nbsp; 回溯算法
</a>
</li>
@@ -1820,7 +1901,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/permutations_problem/" class="md-nav__link">
12.2. &nbsp; 全排列问题
13.2. &nbsp; 全排列问题
</a>
</li>
@@ -1834,7 +1915,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/subset_sum_problem/" class="md-nav__link">
12.3. &nbsp; 子集和问题
13.3. &nbsp; 子集和问题
</a>
</li>
@@ -1848,7 +1929,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/n_queens_problem/" class="md-nav__link">
12.4. &nbsp; N 皇后问题
13.4. &nbsp; N 皇后问题
</a>
</li>
@@ -1862,7 +1943,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/summary/" class="md-nav__link">
12.5. &nbsp; 小结
13.5. &nbsp; 小结
</a>
</li>
@@ -1890,7 +1971,7 @@
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_14" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_15" checked>
@@ -1917,18 +1998,18 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../">13. &nbsp; &nbsp; 动态规划</a>
<a href="../">14. &nbsp; &nbsp; 动态规划</a>
<label for="__nav_14">
<label for="__nav_15">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_14_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_14">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_15_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_15">
<span class="md-nav__icon md-icon"></span>
13. &nbsp; &nbsp; 动态规划
14. &nbsp; &nbsp; 动态规划
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -1941,7 +2022,7 @@
<li class="md-nav__item">
<a href="../intro_to_dynamic_programming/" class="md-nav__link">
13.1. &nbsp; 初探动态规划New
14.1. &nbsp; 初探动态规划New
</a>
</li>
@@ -1964,12 +2045,12 @@
<label class="md-nav__link md-nav__link--active" for="__toc">
13.2. &nbsp; DP 问题特性New
14.2. &nbsp; DP 问题特性New
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
13.2. &nbsp; DP 问题特性New
14.2. &nbsp; DP 问题特性New
</a>
@@ -1988,15 +2069,15 @@
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#1321" class="md-nav__link">
13.2.1. &nbsp; 最优子结构
<a href="#1421" class="md-nav__link">
14.2.1. &nbsp; 最优子结构
</a>
</li>
<li class="md-nav__item">
<a href="#1322" class="md-nav__link">
13.2.2. &nbsp; 无后效性
<a href="#1422" class="md-nav__link">
14.2.2. &nbsp; 无后效性
</a>
</li>
@@ -2017,7 +2098,7 @@
<li class="md-nav__item">
<a href="../dp_solution_pipeline/" class="md-nav__link">
13.3. &nbsp; DP 解题思路New
14.3. &nbsp; DP 解题思路New
</a>
</li>
@@ -2031,7 +2112,7 @@
<li class="md-nav__item">
<a href="../knapsack_problem/" class="md-nav__link">
13.4. &nbsp; 0-1 背包问题New
14.4. &nbsp; 0-1 背包问题New
</a>
</li>
@@ -2045,7 +2126,7 @@
<li class="md-nav__item">
<a href="../unbounded_knapsack_problem/" class="md-nav__link">
13.5. &nbsp; 完全背包问题New
14.5. &nbsp; 完全背包问题New
</a>
</li>
@@ -2059,7 +2140,7 @@
<li class="md-nav__item">
<a href="../edit_distance_problem/" class="md-nav__link">
13.6. &nbsp; 编辑距离问题New
14.6. &nbsp; 编辑距离问题New
</a>
</li>
@@ -2073,76 +2154,7 @@
<li class="md-nav__item">
<a href="../summary/" class="md-nav__link">
13.7. &nbsp; 小结New
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_15" >
<label class="md-nav__link" for="__nav_15" id="__nav_15_label" tabindex="0">
14. &nbsp; &nbsp; 附录
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_15_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_15">
<span class="md-nav__icon md-icon"></span>
14. &nbsp; &nbsp; 附录
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_appendix/installation/" class="md-nav__link">
14.1. &nbsp; 编程环境安装
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_appendix/contribution/" class="md-nav__link">
14.2. &nbsp; 一起参与创作
14.7. &nbsp; 小结New
</a>
</li>
@@ -2173,6 +2185,75 @@
<label class="md-nav__link" for="__nav_16" id="__nav_16_label" tabindex="0">
15. &nbsp; &nbsp; 附录
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_16_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_16">
<span class="md-nav__icon md-icon"></span>
15. &nbsp; &nbsp; 附录
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_appendix/installation/" class="md-nav__link">
15.1. &nbsp; 编程环境安装
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_appendix/contribution/" class="md-nav__link">
15.2. &nbsp; 一起参与创作
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_17" >
@@ -2185,8 +2266,8 @@
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_16_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_16">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_17_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_17">
<span class="md-nav__icon md-icon"></span>
参考文献
</label>
@@ -2227,15 +2308,15 @@
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#1321" class="md-nav__link">
13.2.1. &nbsp; 最优子结构
<a href="#1421" class="md-nav__link">
14.2.1. &nbsp; 最优子结构
</a>
</li>
<li class="md-nav__item">
<a href="#1322" class="md-nav__link">
13.2.2. &nbsp; 无后效性
<a href="#1422" class="md-nav__link">
14.2.2. &nbsp; 无后效性
</a>
</li>
@@ -2263,10 +2344,10 @@
<h1 id="132">13.2. &nbsp; 动态规划问题特性<a class="headerlink" href="#132" title="Permanent link">&para;</a></h1>
<h1 id="142">14.2. &nbsp; 动态规划问题特性<a class="headerlink" href="#142" title="Permanent link">&para;</a></h1>
<p>在上节中,我们学习了动态规划问题的暴力解法,从递归树中观察到海量的重叠子问题,以及了解到动态规划是如何通过记录解来优化时间复杂度的。</p>
<p>实际上,动态规划最常用来求解最优方案问题,例如寻找最短路径、最大利润、最少时间等。<strong>这类问题不仅包含重叠子问题,往往还具有另外两大特性:最优子结构、无后效性</strong></p>
<h2 id="1321">13.2.1. &nbsp; 最优子结构<a class="headerlink" href="#1321" title="Permanent link">&para;</a></h2>
<h2 id="1421">14.2.1. &nbsp; 最优子结构<a class="headerlink" href="#1421" title="Permanent link">&para;</a></h2>
<p>我们对爬楼梯问题稍作改动,使之更加适合展示最优子结构概念。</p>
<div class="admonition question">
<p class="admonition-title">爬楼梯最小代价</p>
@@ -2484,7 +2565,7 @@ dp[i] = \min(dp[i-1], dp[i-2]) + cost[i]
</div>
</div>
</div>
<h2 id="1322">13.2.2. &nbsp; 无后效性<a class="headerlink" href="#1322" title="Permanent link">&para;</a></h2>
<h2 id="1422">14.2.2. &nbsp; 无后效性<a class="headerlink" href="#1422" title="Permanent link">&para;</a></h2>
<p>「无后效性」是动态规划能够有效解决问题的重要特性之一,定义为:<strong>给定一个确定的状态,它的未来发展只与当前状态有关,而与当前状态过去所经历过的所有状态无关</strong></p>
<p>以爬楼梯问题为例,给定状态 <span class="arithmatex">\(i\)</span> ,它会发展出状态 <span class="arithmatex">\(i+1\)</span> 和状态 <span class="arithmatex">\(i+2\)</span> ,分别对应跳 <span class="arithmatex">\(1\)</span> 步和跳 <span class="arithmatex">\(2\)</span> 步。在做出这两种选择时,我们无需考虑状态 <span class="arithmatex">\(i\)</span> 之前的状态,即它们对状态 <span class="arithmatex">\(i\)</span> 的未来没有影响。</p>
<p>然而,如果我们向爬楼梯问题添加一个约束,情况就不一样了。</p>
@@ -2713,7 +2794,7 @@ dp[i, 2] = dp[i-2, 1] + dp[i-2, 2]
<nav class="md-footer__inner md-grid" aria-label="页脚" >
<a href="../intro_to_dynamic_programming/" class="md-footer__link md-footer__link--prev" aria-label="上一页: 13.1. &amp;nbsp; 初探动态规划New" rel="prev">
<a href="../intro_to_dynamic_programming/" class="md-footer__link md-footer__link--prev" aria-label="上一页: 14.1. &amp;nbsp; 初探动态规划New" rel="prev">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</div>
@@ -2722,20 +2803,20 @@ dp[i, 2] = dp[i-2, 1] + dp[i-2, 2]
上一页
</span>
<div class="md-ellipsis">
13.1. &nbsp; 初探动态规划New
14.1. &nbsp; 初探动态规划New
</div>
</div>
</a>
<a href="../dp_solution_pipeline/" class="md-footer__link md-footer__link--next" aria-label="下一页: 13.3. &amp;nbsp; DP 解题思路New" rel="next">
<a href="../dp_solution_pipeline/" class="md-footer__link md-footer__link--next" aria-label="下一页: 14.3. &amp;nbsp; DP 解题思路New" rel="next">
<div class="md-footer__title">
<span class="md-footer__direction">
下一页
</span>
<div class="md-ellipsis">
13.3. &nbsp; DP 解题思路New
14.3. &nbsp; DP 解题思路New
</div>
</div>
<div class="md-footer__button md-icon">

View File

@@ -25,7 +25,7 @@
<title>13.3.   DP 解题思路New - Hello 算法</title>
<title>14.3.   DP 解题思路New - Hello 算法</title>
@@ -79,7 +79,7 @@
<div data-md-component="skip">
<a href="#133" class="md-skip">
<a href="#143" class="md-skip">
跳转至
</a>
@@ -113,7 +113,7 @@
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
13.3. &nbsp; DP 解题思路New
14.3. &nbsp; DP 解题思路New
</span>
</div>
@@ -1771,6 +1771,87 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../../chapter_divide_and_conquer/">12. &nbsp; &nbsp; 分治</a>
<label for="__nav_13">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_13">
<span class="md-nav__icon md-icon"></span>
12. &nbsp; &nbsp; 分治
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_divide_and_conquer/divide_and_conquer/" class="md-nav__link">
12.1. &nbsp; 分治算法New
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_divide_and_conquer/build_binary_tree/" class="md-nav__link">
12.2. &nbsp; 构建树问题New
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_14" >
@@ -1782,18 +1863,18 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../../chapter_backtracking/">12. &nbsp; &nbsp; 回溯</a>
<a href="../../chapter_backtracking/">13. &nbsp; &nbsp; 回溯</a>
<label for="__nav_13">
<label for="__nav_14">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_13">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_14_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_14">
<span class="md-nav__icon md-icon"></span>
12. &nbsp; &nbsp; 回溯
13. &nbsp; &nbsp; 回溯
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -1806,7 +1887,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/backtracking_algorithm/" class="md-nav__link">
12.1. &nbsp; 回溯算法
13.1. &nbsp; 回溯算法
</a>
</li>
@@ -1820,7 +1901,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/permutations_problem/" class="md-nav__link">
12.2. &nbsp; 全排列问题
13.2. &nbsp; 全排列问题
</a>
</li>
@@ -1834,7 +1915,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/subset_sum_problem/" class="md-nav__link">
12.3. &nbsp; 子集和问题
13.3. &nbsp; 子集和问题
</a>
</li>
@@ -1848,7 +1929,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/n_queens_problem/" class="md-nav__link">
12.4. &nbsp; N 皇后问题
13.4. &nbsp; N 皇后问题
</a>
</li>
@@ -1862,7 +1943,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/summary/" class="md-nav__link">
12.5. &nbsp; 小结
13.5. &nbsp; 小结
</a>
</li>
@@ -1890,7 +1971,7 @@
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_14" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_15" checked>
@@ -1917,18 +1998,18 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../">13. &nbsp; &nbsp; 动态规划</a>
<a href="../">14. &nbsp; &nbsp; 动态规划</a>
<label for="__nav_14">
<label for="__nav_15">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_14_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_14">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_15_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_15">
<span class="md-nav__icon md-icon"></span>
13. &nbsp; &nbsp; 动态规划
14. &nbsp; &nbsp; 动态规划
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -1941,7 +2022,7 @@
<li class="md-nav__item">
<a href="../intro_to_dynamic_programming/" class="md-nav__link">
13.1. &nbsp; 初探动态规划New
14.1. &nbsp; 初探动态规划New
</a>
</li>
@@ -1955,7 +2036,7 @@
<li class="md-nav__item">
<a href="../dp_problem_features/" class="md-nav__link">
13.2. &nbsp; DP 问题特性New
14.2. &nbsp; DP 问题特性New
</a>
</li>
@@ -1978,12 +2059,12 @@
<label class="md-nav__link md-nav__link--active" for="__toc">
13.3. &nbsp; DP 解题思路New
14.3. &nbsp; DP 解题思路New
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
13.3. &nbsp; DP 解题思路New
14.3. &nbsp; DP 解题思路New
</a>
@@ -2002,36 +2083,36 @@
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#1331" class="md-nav__link">
13.3.1. &nbsp; 问题判断
<a href="#1431" class="md-nav__link">
14.3.1. &nbsp; 问题判断
</a>
</li>
<li class="md-nav__item">
<a href="#1332" class="md-nav__link">
13.3.2. &nbsp; 问题求解
<a href="#1432" class="md-nav__link">
14.3.2. &nbsp; 问题求解
</a>
</li>
<li class="md-nav__item">
<a href="#1333" class="md-nav__link">
13.3.3. &nbsp; 方法一:暴力搜索
<a href="#1433" class="md-nav__link">
14.3.3. &nbsp; 方法一:暴力搜索
</a>
</li>
<li class="md-nav__item">
<a href="#1334" class="md-nav__link">
13.3.4. &nbsp; 方法二:记忆化搜索
<a href="#1434" class="md-nav__link">
14.3.4. &nbsp; 方法二:记忆化搜索
</a>
</li>
<li class="md-nav__item">
<a href="#1335" class="md-nav__link">
13.3.5. &nbsp; 方法三:动态规划
<a href="#1435" class="md-nav__link">
14.3.5. &nbsp; 方法三:动态规划
</a>
</li>
@@ -2052,7 +2133,7 @@
<li class="md-nav__item">
<a href="../knapsack_problem/" class="md-nav__link">
13.4. &nbsp; 0-1 背包问题New
14.4. &nbsp; 0-1 背包问题New
</a>
</li>
@@ -2066,7 +2147,7 @@
<li class="md-nav__item">
<a href="../unbounded_knapsack_problem/" class="md-nav__link">
13.5. &nbsp; 完全背包问题New
14.5. &nbsp; 完全背包问题New
</a>
</li>
@@ -2080,7 +2161,7 @@
<li class="md-nav__item">
<a href="../edit_distance_problem/" class="md-nav__link">
13.6. &nbsp; 编辑距离问题New
14.6. &nbsp; 编辑距离问题New
</a>
</li>
@@ -2094,76 +2175,7 @@
<li class="md-nav__item">
<a href="../summary/" class="md-nav__link">
13.7. &nbsp; 小结New
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_15" >
<label class="md-nav__link" for="__nav_15" id="__nav_15_label" tabindex="0">
14. &nbsp; &nbsp; 附录
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_15_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_15">
<span class="md-nav__icon md-icon"></span>
14. &nbsp; &nbsp; 附录
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_appendix/installation/" class="md-nav__link">
14.1. &nbsp; 编程环境安装
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_appendix/contribution/" class="md-nav__link">
14.2. &nbsp; 一起参与创作
14.7. &nbsp; 小结New
</a>
</li>
@@ -2194,6 +2206,75 @@
<label class="md-nav__link" for="__nav_16" id="__nav_16_label" tabindex="0">
15. &nbsp; &nbsp; 附录
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_16_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_16">
<span class="md-nav__icon md-icon"></span>
15. &nbsp; &nbsp; 附录
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_appendix/installation/" class="md-nav__link">
15.1. &nbsp; 编程环境安装
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_appendix/contribution/" class="md-nav__link">
15.2. &nbsp; 一起参与创作
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_17" >
@@ -2206,8 +2287,8 @@
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_16_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_16">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_17_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_17">
<span class="md-nav__icon md-icon"></span>
参考文献
</label>
@@ -2248,36 +2329,36 @@
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#1331" class="md-nav__link">
13.3.1. &nbsp; 问题判断
<a href="#1431" class="md-nav__link">
14.3.1. &nbsp; 问题判断
</a>
</li>
<li class="md-nav__item">
<a href="#1332" class="md-nav__link">
13.3.2. &nbsp; 问题求解
<a href="#1432" class="md-nav__link">
14.3.2. &nbsp; 问题求解
</a>
</li>
<li class="md-nav__item">
<a href="#1333" class="md-nav__link">
13.3.3. &nbsp; 方法一:暴力搜索
<a href="#1433" class="md-nav__link">
14.3.3. &nbsp; 方法一:暴力搜索
</a>
</li>
<li class="md-nav__item">
<a href="#1334" class="md-nav__link">
13.3.4. &nbsp; 方法二:记忆化搜索
<a href="#1434" class="md-nav__link">
14.3.4. &nbsp; 方法二:记忆化搜索
</a>
</li>
<li class="md-nav__item">
<a href="#1335" class="md-nav__link">
13.3.5. &nbsp; 方法三:动态规划
<a href="#1435" class="md-nav__link">
14.3.5. &nbsp; 方法三:动态规划
</a>
</li>
@@ -2305,13 +2386,13 @@
<h1 id="133">13.3. &nbsp; 动态规划解题思路<a class="headerlink" href="#133" title="Permanent link">&para;</a></h1>
<h1 id="143">14.3. &nbsp; 动态规划解题思路<a class="headerlink" href="#143" title="Permanent link">&para;</a></h1>
<p>上两节介绍了动态规划问题的主要特征,接下来我们一起探究两个更加实用的问题:</p>
<ol>
<li>如何判断一个问题是不是动态规划问题?</li>
<li>求解动态规划问题该从何处入手,完整步骤是什么?</li>
</ol>
<h2 id="1331">13.3.1. &nbsp; 问题判断<a class="headerlink" href="#1331" title="Permanent link">&para;</a></h2>
<h2 id="1431">14.3.1. &nbsp; 问题判断<a class="headerlink" href="#1431" title="Permanent link">&para;</a></h2>
<p>总的来说,如果一个问题包含重叠子问题、最优子结构,并满足无后效性,那么它通常就适合用动态规划求解,但我们很难从问题描述上直接提取出这些特性。因此我们通常会放宽条件,<strong>先观察问题是否适合使用回溯(穷举)解决</strong></p>
<p><strong>适合用回溯解决的问题通常满足“决策树模型”</strong>,这种问题可以使用树形结构来描述,其中每一个节点代表一个决策,每一条路径代表一个决策序列。</p>
<p>换句话说,如果问题包含明确的决策概念,并且解是通过一系列决策产生的,那么它就满足决策树模型,通常可以使用回溯来解决。</p>
@@ -2326,7 +2407,7 @@
<li>问题描述中有明显的排列组合的特征,需要返回具体的多个方案。</li>
</ul>
<p>如果一个问题满足决策树模型,并具有较为明显的“加分项“,我们就可以假设它是一个动态规划问题,并尝试求解它。</p>
<h2 id="1332">13.3.2. &nbsp; 问题求解<a class="headerlink" href="#1332" title="Permanent link">&para;</a></h2>
<h2 id="1432">14.3.2. &nbsp; 问题求解<a class="headerlink" href="#1432" title="Permanent link">&para;</a></h2>
<p>动态规划的解题流程可能会因问题的性质和难度而有所不同,但通常遵循以下步骤:描述决策,定义状态,建立 <span class="arithmatex">\(dp\)</span> 表,推导状态转移方程,确定边界条件等。</p>
<p>为了更形象地展示解题步骤,我们使用一个经典问题「最小路径和」来举例。</p>
<div class="admonition question">
@@ -2374,7 +2455,7 @@ dp[i, j] = \min(dp[i-1, j], dp[i, j-1]) + grid[i, j]
<p>边界条件即初始状态,在搜索中用于剪枝,在动态规划中用于初始化 <span class="arithmatex">\(dp\)</span> 表。状态转移顺序的核心是要保证在计算当前问题时,所有它依赖的更小子问题都已经被正确地计算出来。</p>
</div>
<p>接下来,我们就可以实现动态规划代码了。然而,由于子问题分解是一种从顶至底的思想,因此按照“暴力搜索 <span class="arithmatex">\(\rightarrow\)</span> 记忆化搜索 <span class="arithmatex">\(\rightarrow\)</span> 动态规划”的顺序实现更加符合思维习惯。</p>
<h2 id="1333">13.3.3. &nbsp; 方法一:暴力搜索<a class="headerlink" href="#1333" title="Permanent link">&para;</a></h2>
<h2 id="1433">14.3.3. &nbsp; 方法一:暴力搜索<a class="headerlink" href="#1433" title="Permanent link">&para;</a></h2>
<p>从状态 <span class="arithmatex">\([i, j]\)</span> 开始搜索,不断分解为更小的状态 <span class="arithmatex">\([i-1, j]\)</span><span class="arithmatex">\([i, j-1]\)</span> ,包括以下递归要素:</p>
<ul>
<li><strong>递归参数</strong>:状态 <span class="arithmatex">\([i, j]\)</span> <strong>返回值</strong>:从 <span class="arithmatex">\([0, 0]\)</span><span class="arithmatex">\([i, j]\)</span> 的最小路径和 <span class="arithmatex">\(dp[i, j]\)</span> </li>
@@ -2492,7 +2573,7 @@ dp[i, j] = \min(dp[i-1, j], dp[i, j-1]) + grid[i, j]
<p align="center"> Fig. 暴力搜索递归树 </p>
<p>每个状态都有向下和向右两种选择,从左上角走到右下角总共需要 <span class="arithmatex">\(m + n - 2\)</span> 步,所以最差时间复杂度为 <span class="arithmatex">\(O(2^{m + n})\)</span> 。请注意,这种计算方式未考虑临近网格边界的情况,当到达网络边界时只剩下一种选择。因此实际的路径数量会少一些。</p>
<h2 id="1334">13.3.4. &nbsp; 方法二:记忆化搜索<a class="headerlink" href="#1334" title="Permanent link">&para;</a></h2>
<h2 id="1434">14.3.4. &nbsp; 方法二:记忆化搜索<a class="headerlink" href="#1434" title="Permanent link">&para;</a></h2>
<p>为了避免重复计算重叠子问题,我们引入一个和网格 <code>grid</code> 相同尺寸的记忆列表 <code>mem</code> ,用于记录各个子问题的解,提升搜索效率。</p>
<div class="tabbed-set tabbed-alternate" data-tabs="2:11"><input checked="checked" id="__tabbed_2_1" name="__tabbed_2" type="radio" /><input id="__tabbed_2_2" name="__tabbed_2" type="radio" /><input id="__tabbed_2_3" name="__tabbed_2" type="radio" /><input id="__tabbed_2_4" name="__tabbed_2" type="radio" /><input id="__tabbed_2_5" name="__tabbed_2" type="radio" /><input id="__tabbed_2_6" name="__tabbed_2" type="radio" /><input id="__tabbed_2_7" name="__tabbed_2" type="radio" /><input id="__tabbed_2_8" name="__tabbed_2" type="radio" /><input id="__tabbed_2_9" name="__tabbed_2" type="radio" /><input id="__tabbed_2_10" name="__tabbed_2" type="radio" /><input id="__tabbed_2_11" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="__tabbed_2_1">Java</label><label for="__tabbed_2_2">C++</label><label for="__tabbed_2_3">Python</label><label for="__tabbed_2_4">Go</label><label for="__tabbed_2_5">JavaScript</label><label for="__tabbed_2_6">TypeScript</label><label for="__tabbed_2_7">C</label><label for="__tabbed_2_8">C#</label><label for="__tabbed_2_9">Swift</label><label for="__tabbed_2_10">Zig</label><label for="__tabbed_2_11">Dart</label></div>
<div class="tabbed-content">
@@ -2624,7 +2705,7 @@ dp[i, j] = \min(dp[i-1, j], dp[i, j-1]) + grid[i, j]
<p><img alt="记忆化搜索递归树" src="../dp_solution_pipeline.assets/min_path_sum_dfs_mem.png" /></p>
<p align="center"> Fig. 记忆化搜索递归树 </p>
<h2 id="1335">13.3.5. &nbsp; 方法三:动态规划<a class="headerlink" href="#1335" title="Permanent link">&para;</a></h2>
<h2 id="1435">14.3.5. &nbsp; 方法三:动态规划<a class="headerlink" href="#1435" title="Permanent link">&para;</a></h2>
<p>动态规划代码是从底至顶的,仅需循环即可实现。</p>
<div class="tabbed-set tabbed-alternate" data-tabs="3:11"><input checked="checked" id="__tabbed_3_1" name="__tabbed_3" type="radio" /><input id="__tabbed_3_2" name="__tabbed_3" type="radio" /><input id="__tabbed_3_3" name="__tabbed_3" type="radio" /><input id="__tabbed_3_4" name="__tabbed_3" type="radio" /><input id="__tabbed_3_5" name="__tabbed_3" type="radio" /><input id="__tabbed_3_6" name="__tabbed_3" type="radio" /><input id="__tabbed_3_7" name="__tabbed_3" type="radio" /><input id="__tabbed_3_8" name="__tabbed_3" type="radio" /><input id="__tabbed_3_9" name="__tabbed_3" type="radio" /><input id="__tabbed_3_10" name="__tabbed_3" type="radio" /><input id="__tabbed_3_11" name="__tabbed_3" type="radio" /><div class="tabbed-labels"><label for="__tabbed_3_1">Java</label><label for="__tabbed_3_2">C++</label><label for="__tabbed_3_3">Python</label><label for="__tabbed_3_4">Go</label><label for="__tabbed_3_5">JavaScript</label><label for="__tabbed_3_6">TypeScript</label><label for="__tabbed_3_7">C</label><label for="__tabbed_3_8">C#</label><label for="__tabbed_3_9">Swift</label><label for="__tabbed_3_10">Zig</label><label for="__tabbed_3_11">Dart</label></div>
<div class="tabbed-content">
@@ -2997,7 +3078,7 @@ dp[i, j] = \min(dp[i-1, j], dp[i, j-1]) + grid[i, j]
<nav class="md-footer__inner md-grid" aria-label="页脚" >
<a href="../dp_problem_features/" class="md-footer__link md-footer__link--prev" aria-label="上一页: 13.2. &amp;nbsp; DP 问题特性New" rel="prev">
<a href="../dp_problem_features/" class="md-footer__link md-footer__link--prev" aria-label="上一页: 14.2. &amp;nbsp; DP 问题特性New" rel="prev">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</div>
@@ -3006,20 +3087,20 @@ dp[i, j] = \min(dp[i-1, j], dp[i, j-1]) + grid[i, j]
上一页
</span>
<div class="md-ellipsis">
13.2. &nbsp; DP 问题特性New
14.2. &nbsp; DP 问题特性New
</div>
</div>
</a>
<a href="../knapsack_problem/" class="md-footer__link md-footer__link--next" aria-label="下一页: 13.4. &amp;nbsp; 0-1 背包问题New" rel="next">
<a href="../knapsack_problem/" class="md-footer__link md-footer__link--next" aria-label="下一页: 14.4. &amp;nbsp; 0-1 背包问题New" rel="next">
<div class="md-footer__title">
<span class="md-footer__direction">
下一页
</span>
<div class="md-ellipsis">
13.4. &nbsp; 0-1 背包问题New
14.4. &nbsp; 0-1 背包问题New
</div>
</div>
<div class="md-footer__button md-icon">

View File

@@ -25,7 +25,7 @@
<title>13.6.   编辑距离问题New - Hello 算法</title>
<title>14.6.   编辑距离问题New - Hello 算法</title>
@@ -79,7 +79,7 @@
<div data-md-component="skip">
<a href="#136" class="md-skip">
<a href="#146" class="md-skip">
跳转至
</a>
@@ -113,7 +113,7 @@
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
13.6. &nbsp; 编辑距离问题New
14.6. &nbsp; 编辑距离问题New
</span>
</div>
@@ -1771,6 +1771,87 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../../chapter_divide_and_conquer/">12. &nbsp; &nbsp; 分治</a>
<label for="__nav_13">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_13">
<span class="md-nav__icon md-icon"></span>
12. &nbsp; &nbsp; 分治
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_divide_and_conquer/divide_and_conquer/" class="md-nav__link">
12.1. &nbsp; 分治算法New
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_divide_and_conquer/build_binary_tree/" class="md-nav__link">
12.2. &nbsp; 构建树问题New
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_14" >
@@ -1782,18 +1863,18 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../../chapter_backtracking/">12. &nbsp; &nbsp; 回溯</a>
<a href="../../chapter_backtracking/">13. &nbsp; &nbsp; 回溯</a>
<label for="__nav_13">
<label for="__nav_14">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_13">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_14_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_14">
<span class="md-nav__icon md-icon"></span>
12. &nbsp; &nbsp; 回溯
13. &nbsp; &nbsp; 回溯
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -1806,7 +1887,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/backtracking_algorithm/" class="md-nav__link">
12.1. &nbsp; 回溯算法
13.1. &nbsp; 回溯算法
</a>
</li>
@@ -1820,7 +1901,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/permutations_problem/" class="md-nav__link">
12.2. &nbsp; 全排列问题
13.2. &nbsp; 全排列问题
</a>
</li>
@@ -1834,7 +1915,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/subset_sum_problem/" class="md-nav__link">
12.3. &nbsp; 子集和问题
13.3. &nbsp; 子集和问题
</a>
</li>
@@ -1848,7 +1929,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/n_queens_problem/" class="md-nav__link">
12.4. &nbsp; N 皇后问题
13.4. &nbsp; N 皇后问题
</a>
</li>
@@ -1862,7 +1943,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/summary/" class="md-nav__link">
12.5. &nbsp; 小结
13.5. &nbsp; 小结
</a>
</li>
@@ -1890,7 +1971,7 @@
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_14" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_15" checked>
@@ -1917,18 +1998,18 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../">13. &nbsp; &nbsp; 动态规划</a>
<a href="../">14. &nbsp; &nbsp; 动态规划</a>
<label for="__nav_14">
<label for="__nav_15">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_14_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_14">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_15_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_15">
<span class="md-nav__icon md-icon"></span>
13. &nbsp; &nbsp; 动态规划
14. &nbsp; &nbsp; 动态规划
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -1941,7 +2022,7 @@
<li class="md-nav__item">
<a href="../intro_to_dynamic_programming/" class="md-nav__link">
13.1. &nbsp; 初探动态规划New
14.1. &nbsp; 初探动态规划New
</a>
</li>
@@ -1955,7 +2036,7 @@
<li class="md-nav__item">
<a href="../dp_problem_features/" class="md-nav__link">
13.2. &nbsp; DP 问题特性New
14.2. &nbsp; DP 问题特性New
</a>
</li>
@@ -1969,7 +2050,7 @@
<li class="md-nav__item">
<a href="../dp_solution_pipeline/" class="md-nav__link">
13.3. &nbsp; DP 解题思路New
14.3. &nbsp; DP 解题思路New
</a>
</li>
@@ -1983,7 +2064,7 @@
<li class="md-nav__item">
<a href="../knapsack_problem/" class="md-nav__link">
13.4. &nbsp; 0-1 背包问题New
14.4. &nbsp; 0-1 背包问题New
</a>
</li>
@@ -1997,7 +2078,7 @@
<li class="md-nav__item">
<a href="../unbounded_knapsack_problem/" class="md-nav__link">
13.5. &nbsp; 完全背包问题New
14.5. &nbsp; 完全背包问题New
</a>
</li>
@@ -2020,7 +2101,7 @@
<a href="./" class="md-nav__link md-nav__link--active">
13.6. &nbsp; 编辑距离问题New
14.6. &nbsp; 编辑距离问题New
</a>
</li>
@@ -2035,76 +2116,7 @@
<li class="md-nav__item">
<a href="../summary/" class="md-nav__link">
13.7. &nbsp; 小结New
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_15" >
<label class="md-nav__link" for="__nav_15" id="__nav_15_label" tabindex="0">
14. &nbsp; &nbsp; 附录
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_15_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_15">
<span class="md-nav__icon md-icon"></span>
14. &nbsp; &nbsp; 附录
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_appendix/installation/" class="md-nav__link">
14.1. &nbsp; 编程环境安装
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_appendix/contribution/" class="md-nav__link">
14.2. &nbsp; 一起参与创作
14.7. &nbsp; 小结New
</a>
</li>
@@ -2135,6 +2147,75 @@
<label class="md-nav__link" for="__nav_16" id="__nav_16_label" tabindex="0">
15. &nbsp; &nbsp; 附录
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_16_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_16">
<span class="md-nav__icon md-icon"></span>
15. &nbsp; &nbsp; 附录
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_appendix/installation/" class="md-nav__link">
15.1. &nbsp; 编程环境安装
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_appendix/contribution/" class="md-nav__link">
15.2. &nbsp; 一起参与创作
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_17" >
@@ -2147,8 +2228,8 @@
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_16_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_16">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_17_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_17">
<span class="md-nav__icon md-icon"></span>
参考文献
</label>
@@ -2203,7 +2284,7 @@
<h1 id="136">13.6. &nbsp; 编辑距离问题<a class="headerlink" href="#136" title="Permanent link">&para;</a></h1>
<h1 id="146">14.6. &nbsp; 编辑距离问题<a class="headerlink" href="#146" title="Permanent link">&para;</a></h1>
<p>编辑距离,也被称为 Levenshtein 距离,是两个字符串之间互相转换的最小修改次数,通常用于在信息检索和自然语言处理中度量两个序列的相似度。</p>
<div class="admonition question">
<p class="admonition-title">Question</p>
@@ -2347,7 +2428,31 @@ dp[i, j] = dp[i-1, j-1]
</code></pre></div>
</div>
<div class="tabbed-block">
<div class="highlight"><span class="filename">edit_distance.cs</span><pre><span></span><code><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a><span class="na">[class]</span><span class="p">{</span><span class="n">edit_distance</span><span class="p">}</span><span class="o">-</span><span class="p">[</span><span class="n">func</span><span class="p">]{</span><span class="n">editDistanceDP</span><span class="p">}</span>
<div class="highlight"><span class="filename">edit_distance.cs</span><pre><span></span><code><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a><span class="cm">/* 编辑距离:动态规划 */</span>
<a id="__codelineno-7-2" name="__codelineno-7-2" href="#__codelineno-7-2"></a><span class="kt">int</span><span class="w"> </span><span class="nf">editDistanceDP</span><span class="p">(</span><span class="kt">string</span><span class="w"> </span><span class="n">s</span><span class="p">,</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="n">t</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-7-3" name="__codelineno-7-3" href="#__codelineno-7-3"></a><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">s</span><span class="p">.</span><span class="n">Length</span><span class="p">,</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">t</span><span class="p">.</span><span class="n">Length</span><span class="p">;</span>
<a id="__codelineno-7-4" name="__codelineno-7-4" href="#__codelineno-7-4"></a><span class="w"> </span><span class="kt">int</span><span class="p">[,]</span><span class="w"> </span><span class="n">dp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">int</span><span class="p">[</span><span class="n">n</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="m">1</span><span class="p">,</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="m">1</span><span class="p">];</span>
<a id="__codelineno-7-5" name="__codelineno-7-5" href="#__codelineno-7-5"></a><span class="w"> </span><span class="c1">// 状态转移:首行首列</span>
<a id="__codelineno-7-6" name="__codelineno-7-6" href="#__codelineno-7-6"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">1</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="n">n</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-7-7" name="__codelineno-7-7" href="#__codelineno-7-7"></a><span class="w"> </span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="m">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">i</span><span class="p">;</span>
<a id="__codelineno-7-8" name="__codelineno-7-8" href="#__codelineno-7-8"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-7-9" name="__codelineno-7-9" href="#__codelineno-7-9"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">1</span><span class="p">;</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="n">m</span><span class="p">;</span><span class="w"> </span><span class="n">j</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-7-10" name="__codelineno-7-10" href="#__codelineno-7-10"></a><span class="w"> </span><span class="n">dp</span><span class="p">[</span><span class="m">0</span><span class="p">,</span><span class="w"> </span><span class="n">j</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">j</span><span class="p">;</span>
<a id="__codelineno-7-11" name="__codelineno-7-11" href="#__codelineno-7-11"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-7-12" name="__codelineno-7-12" href="#__codelineno-7-12"></a><span class="w"> </span><span class="c1">// 状态转移:其余行列</span>
<a id="__codelineno-7-13" name="__codelineno-7-13" href="#__codelineno-7-13"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">1</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="n">n</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-7-14" name="__codelineno-7-14" href="#__codelineno-7-14"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">1</span><span class="p">;</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="n">m</span><span class="p">;</span><span class="w"> </span><span class="n">j</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-7-15" name="__codelineno-7-15" href="#__codelineno-7-15"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">]</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">t</span><span class="p">[</span><span class="n">j</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">])</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-7-16" name="__codelineno-7-16" href="#__codelineno-7-16"></a><span class="w"> </span><span class="c1">// 若两字符相等,则直接跳过此两字符</span>
<a id="__codelineno-7-17" name="__codelineno-7-17" href="#__codelineno-7-17"></a><span class="w"> </span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">j</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">,</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">];</span>
<a id="__codelineno-7-18" name="__codelineno-7-18" href="#__codelineno-7-18"></a><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-7-19" name="__codelineno-7-19" href="#__codelineno-7-19"></a><span class="w"> </span><span class="c1">// 最少编辑步数 = 插入、删除、替换这三种操作的最少编辑步数 + 1</span>
<a id="__codelineno-7-20" name="__codelineno-7-20" href="#__codelineno-7-20"></a><span class="w"> </span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">j</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Math</span><span class="p">.</span><span class="n">Min</span><span class="p">(</span><span class="n">Math</span><span class="p">.</span><span class="n">Min</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">],</span><span class="w"> </span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">,</span><span class="w"> </span><span class="n">j</span><span class="p">]),</span><span class="w"> </span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">,</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">])</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="m">1</span><span class="p">;</span>
<a id="__codelineno-7-21" name="__codelineno-7-21" href="#__codelineno-7-21"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-7-22" name="__codelineno-7-22" href="#__codelineno-7-22"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-7-23" name="__codelineno-7-23" href="#__codelineno-7-23"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-7-24" name="__codelineno-7-24" href="#__codelineno-7-24"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">dp</span><span class="p">[</span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="n">m</span><span class="p">];</span>
<a id="__codelineno-7-25" name="__codelineno-7-25" href="#__codelineno-7-25"></a><span class="p">}</span>
</code></pre></div>
</div>
<div class="tabbed-block">
@@ -2523,7 +2628,34 @@ dp[i, j] = dp[i-1, j-1]
</code></pre></div>
</div>
<div class="tabbed-block">
<div class="highlight"><span class="filename">edit_distance.cs</span><pre><span></span><code><a id="__codelineno-18-1" name="__codelineno-18-1" href="#__codelineno-18-1"></a><span class="na">[class]</span><span class="p">{</span><span class="n">edit_distance</span><span class="p">}</span><span class="o">-</span><span class="p">[</span><span class="n">func</span><span class="p">]{</span><span class="n">editDistanceDPComp</span><span class="p">}</span>
<div class="highlight"><span class="filename">edit_distance.cs</span><pre><span></span><code><a id="__codelineno-18-1" name="__codelineno-18-1" href="#__codelineno-18-1"></a><span class="cm">/* 编辑距离:状态压缩后的动态规划 */</span>
<a id="__codelineno-18-2" name="__codelineno-18-2" href="#__codelineno-18-2"></a><span class="kt">int</span><span class="w"> </span><span class="nf">editDistanceDPComp</span><span class="p">(</span><span class="kt">string</span><span class="w"> </span><span class="n">s</span><span class="p">,</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="n">t</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-18-3" name="__codelineno-18-3" href="#__codelineno-18-3"></a><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">s</span><span class="p">.</span><span class="n">Length</span><span class="p">,</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">t</span><span class="p">.</span><span class="n">Length</span><span class="p">;</span>
<a id="__codelineno-18-4" name="__codelineno-18-4" href="#__codelineno-18-4"></a><span class="w"> </span><span class="kt">int</span><span class="p">[]</span><span class="w"> </span><span class="n">dp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">int</span><span class="p">[</span><span class="n">m</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="m">1</span><span class="p">];</span>
<a id="__codelineno-18-5" name="__codelineno-18-5" href="#__codelineno-18-5"></a><span class="w"> </span><span class="c1">// 状态转移:首行</span>
<a id="__codelineno-18-6" name="__codelineno-18-6" href="#__codelineno-18-6"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">1</span><span class="p">;</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="n">m</span><span class="p">;</span><span class="w"> </span><span class="n">j</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-18-7" name="__codelineno-18-7" href="#__codelineno-18-7"></a><span class="w"> </span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">j</span><span class="p">;</span>
<a id="__codelineno-18-8" name="__codelineno-18-8" href="#__codelineno-18-8"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-18-9" name="__codelineno-18-9" href="#__codelineno-18-9"></a><span class="w"> </span><span class="c1">// 状态转移:其余行</span>
<a id="__codelineno-18-10" name="__codelineno-18-10" href="#__codelineno-18-10"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">1</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="n">n</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-18-11" name="__codelineno-18-11" href="#__codelineno-18-11"></a><span class="w"> </span><span class="c1">// 状态转移:首列</span>
<a id="__codelineno-18-12" name="__codelineno-18-12" href="#__codelineno-18-12"></a><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">leftup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">dp</span><span class="p">[</span><span class="m">0</span><span class="p">];</span><span class="w"> </span><span class="c1">// 暂存 dp[i-1, j-1]</span>
<a id="__codelineno-18-13" name="__codelineno-18-13" href="#__codelineno-18-13"></a><span class="w"> </span><span class="n">dp</span><span class="p">[</span><span class="m">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">i</span><span class="p">;</span>
<a id="__codelineno-18-14" name="__codelineno-18-14" href="#__codelineno-18-14"></a><span class="w"> </span><span class="c1">// 状态转移:其余列</span>
<a id="__codelineno-18-15" name="__codelineno-18-15" href="#__codelineno-18-15"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">1</span><span class="p">;</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="n">m</span><span class="p">;</span><span class="w"> </span><span class="n">j</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-18-16" name="__codelineno-18-16" href="#__codelineno-18-16"></a><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">];</span>
<a id="__codelineno-18-17" name="__codelineno-18-17" href="#__codelineno-18-17"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">]</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">t</span><span class="p">[</span><span class="n">j</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">])</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-18-18" name="__codelineno-18-18" href="#__codelineno-18-18"></a><span class="w"> </span><span class="c1">// 若两字符相等,则直接跳过此两字符</span>
<a id="__codelineno-18-19" name="__codelineno-18-19" href="#__codelineno-18-19"></a><span class="w"> </span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">leftup</span><span class="p">;</span>
<a id="__codelineno-18-20" name="__codelineno-18-20" href="#__codelineno-18-20"></a><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-18-21" name="__codelineno-18-21" href="#__codelineno-18-21"></a><span class="w"> </span><span class="c1">// 最少编辑步数 = 插入、删除、替换这三种操作的最少编辑步数 + 1</span>
<a id="__codelineno-18-22" name="__codelineno-18-22" href="#__codelineno-18-22"></a><span class="w"> </span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Math</span><span class="p">.</span><span class="n">Min</span><span class="p">(</span><span class="n">Math</span><span class="p">.</span><span class="n">Min</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">],</span><span class="w"> </span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]),</span><span class="w"> </span><span class="n">leftup</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="m">1</span><span class="p">;</span>
<a id="__codelineno-18-23" name="__codelineno-18-23" href="#__codelineno-18-23"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-18-24" name="__codelineno-18-24" href="#__codelineno-18-24"></a><span class="w"> </span><span class="n">leftup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">temp</span><span class="p">;</span><span class="w"> </span><span class="c1">// 更新为下一轮的 dp[i-1, j-1]</span>
<a id="__codelineno-18-25" name="__codelineno-18-25" href="#__codelineno-18-25"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-18-26" name="__codelineno-18-26" href="#__codelineno-18-26"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-18-27" name="__codelineno-18-27" href="#__codelineno-18-27"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">dp</span><span class="p">[</span><span class="n">m</span><span class="p">];</span>
<a id="__codelineno-18-28" name="__codelineno-18-28" href="#__codelineno-18-28"></a><span class="p">}</span>
</code></pre></div>
</div>
<div class="tabbed-block">
@@ -2617,7 +2749,7 @@ dp[i, j] = dp[i-1, j-1]
<nav class="md-footer__inner md-grid" aria-label="页脚" >
<a href="../unbounded_knapsack_problem/" class="md-footer__link md-footer__link--prev" aria-label="上一页: 13.5. &amp;nbsp; 完全背包问题New" rel="prev">
<a href="../unbounded_knapsack_problem/" class="md-footer__link md-footer__link--prev" aria-label="上一页: 14.5. &amp;nbsp; 完全背包问题New" rel="prev">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</div>
@@ -2626,20 +2758,20 @@ dp[i, j] = dp[i-1, j-1]
上一页
</span>
<div class="md-ellipsis">
13.5. &nbsp; 完全背包问题New
14.5. &nbsp; 完全背包问题New
</div>
</div>
</a>
<a href="../summary/" class="md-footer__link md-footer__link--next" aria-label="下一页: 13.7. &amp;nbsp; 小结New" rel="next">
<a href="../summary/" class="md-footer__link md-footer__link--next" aria-label="下一页: 14.7. &amp;nbsp; 小结New" rel="next">
<div class="md-footer__title">
<span class="md-footer__direction">
下一页
</span>
<div class="md-ellipsis">
13.7. &nbsp; 小结New
14.7. &nbsp; 小结New
</div>
</div>
<div class="md-footer__button md-icon">

View File

@@ -25,7 +25,7 @@
<title>13.   动态规划 - Hello 算法</title>
<title>14.   动态规划 - Hello 算法</title>
@@ -79,7 +79,7 @@
<div data-md-component="skip">
<a href="#13" class="md-skip">
<a href="#14" class="md-skip">
跳转至
</a>
@@ -113,7 +113,7 @@
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
13. &nbsp; 动态规划
14. &nbsp; 动态规划
</span>
</div>
@@ -1771,6 +1771,87 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../chapter_divide_and_conquer/">12. &nbsp; &nbsp; 分治</a>
<label for="__nav_13">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_13">
<span class="md-nav__icon md-icon"></span>
12. &nbsp; &nbsp; 分治
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../chapter_divide_and_conquer/divide_and_conquer/" class="md-nav__link">
12.1. &nbsp; 分治算法New
</a>
</li>
<li class="md-nav__item">
<a href="../chapter_divide_and_conquer/build_binary_tree/" class="md-nav__link">
12.2. &nbsp; 构建树问题New
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_14" >
@@ -1782,18 +1863,18 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../chapter_backtracking/">12. &nbsp; &nbsp; 回溯</a>
<a href="../chapter_backtracking/">13. &nbsp; &nbsp; 回溯</a>
<label for="__nav_13">
<label for="__nav_14">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_13">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_14_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_14">
<span class="md-nav__icon md-icon"></span>
12. &nbsp; &nbsp; 回溯
13. &nbsp; &nbsp; 回溯
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -1806,7 +1887,7 @@
<li class="md-nav__item">
<a href="../chapter_backtracking/backtracking_algorithm/" class="md-nav__link">
12.1. &nbsp; 回溯算法
13.1. &nbsp; 回溯算法
</a>
</li>
@@ -1820,7 +1901,7 @@
<li class="md-nav__item">
<a href="../chapter_backtracking/permutations_problem/" class="md-nav__link">
12.2. &nbsp; 全排列问题
13.2. &nbsp; 全排列问题
</a>
</li>
@@ -1834,7 +1915,7 @@
<li class="md-nav__item">
<a href="../chapter_backtracking/subset_sum_problem/" class="md-nav__link">
12.3. &nbsp; 子集和问题
13.3. &nbsp; 子集和问题
</a>
</li>
@@ -1848,7 +1929,7 @@
<li class="md-nav__item">
<a href="../chapter_backtracking/n_queens_problem/" class="md-nav__link">
12.4. &nbsp; N 皇后问题
13.4. &nbsp; N 皇后问题
</a>
</li>
@@ -1862,7 +1943,7 @@
<li class="md-nav__item">
<a href="../chapter_backtracking/summary/" class="md-nav__link">
12.5. &nbsp; 小结
13.5. &nbsp; 小结
</a>
</li>
@@ -1890,7 +1971,7 @@
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_14" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_15" checked>
@@ -1917,18 +1998,18 @@
<div class="md-nav__link md-nav__link--index md-nav__link--active">
<a href="./">13. &nbsp; &nbsp; 动态规划</a>
<a href="./">14. &nbsp; &nbsp; 动态规划</a>
<label for="__nav_14">
<label for="__nav_15">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_14_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_14">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_15_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_15">
<span class="md-nav__icon md-icon"></span>
13. &nbsp; &nbsp; 动态规划
14. &nbsp; &nbsp; 动态规划
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -1941,7 +2022,7 @@
<li class="md-nav__item">
<a href="intro_to_dynamic_programming/" class="md-nav__link">
13.1. &nbsp; 初探动态规划New
14.1. &nbsp; 初探动态规划New
</a>
</li>
@@ -1955,7 +2036,7 @@
<li class="md-nav__item">
<a href="dp_problem_features/" class="md-nav__link">
13.2. &nbsp; DP 问题特性New
14.2. &nbsp; DP 问题特性New
</a>
</li>
@@ -1969,7 +2050,7 @@
<li class="md-nav__item">
<a href="dp_solution_pipeline/" class="md-nav__link">
13.3. &nbsp; DP 解题思路New
14.3. &nbsp; DP 解题思路New
</a>
</li>
@@ -1983,7 +2064,7 @@
<li class="md-nav__item">
<a href="knapsack_problem/" class="md-nav__link">
13.4. &nbsp; 0-1 背包问题New
14.4. &nbsp; 0-1 背包问题New
</a>
</li>
@@ -1997,7 +2078,7 @@
<li class="md-nav__item">
<a href="unbounded_knapsack_problem/" class="md-nav__link">
13.5. &nbsp; 完全背包问题New
14.5. &nbsp; 完全背包问题New
</a>
</li>
@@ -2011,7 +2092,7 @@
<li class="md-nav__item">
<a href="edit_distance_problem/" class="md-nav__link">
13.6. &nbsp; 编辑距离问题New
14.6. &nbsp; 编辑距离问题New
</a>
</li>
@@ -2025,76 +2106,7 @@
<li class="md-nav__item">
<a href="summary/" class="md-nav__link">
13.7. &nbsp; 小结New
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_15" >
<label class="md-nav__link" for="__nav_15" id="__nav_15_label" tabindex="0">
14. &nbsp; &nbsp; 附录
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_15_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_15">
<span class="md-nav__icon md-icon"></span>
14. &nbsp; &nbsp; 附录
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../chapter_appendix/installation/" class="md-nav__link">
14.1. &nbsp; 编程环境安装
</a>
</li>
<li class="md-nav__item">
<a href="../chapter_appendix/contribution/" class="md-nav__link">
14.2. &nbsp; 一起参与创作
14.7. &nbsp; 小结New
</a>
</li>
@@ -2125,6 +2137,75 @@
<label class="md-nav__link" for="__nav_16" id="__nav_16_label" tabindex="0">
15. &nbsp; &nbsp; 附录
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_16_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_16">
<span class="md-nav__icon md-icon"></span>
15. &nbsp; &nbsp; 附录
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../chapter_appendix/installation/" class="md-nav__link">
15.1. &nbsp; 编程环境安装
</a>
</li>
<li class="md-nav__item">
<a href="../chapter_appendix/contribution/" class="md-nav__link">
15.2. &nbsp; 一起参与创作
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_17" >
@@ -2137,8 +2218,8 @@
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_16_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_16">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_17_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_17">
<span class="md-nav__icon md-icon"></span>
参考文献
</label>
@@ -2193,7 +2274,7 @@
<h1 id="13">13. &nbsp; 动态规划<a class="headerlink" href="#13" title="Permanent link">&para;</a></h1>
<h1 id="14">14. &nbsp; 动态规划<a class="headerlink" href="#14" title="Permanent link">&para;</a></h1>
<div class="center-table">
<p><img alt="动态规划" src="../assets/covers/chapter_dynamic_programming.jpg" width="70%" /></p>
</div>
@@ -2274,7 +2355,7 @@
<nav class="md-footer__inner md-grid" aria-label="页脚" >
<a href="../chapter_backtracking/summary/" class="md-footer__link md-footer__link--prev" aria-label="上一页: 12.5. &amp;nbsp; 小结" rel="prev">
<a href="../chapter_backtracking/summary/" class="md-footer__link md-footer__link--prev" aria-label="上一页: 13.5. &amp;nbsp; 小结" rel="prev">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</div>
@@ -2283,20 +2364,20 @@
上一页
</span>
<div class="md-ellipsis">
12.5. &nbsp; 小结
13.5. &nbsp; 小结
</div>
</div>
</a>
<a href="intro_to_dynamic_programming/" class="md-footer__link md-footer__link--next" aria-label="下一页: 13.1. &amp;nbsp; 初探动态规划New" rel="next">
<a href="intro_to_dynamic_programming/" class="md-footer__link md-footer__link--next" aria-label="下一页: 14.1. &amp;nbsp; 初探动态规划New" rel="next">
<div class="md-footer__title">
<span class="md-footer__direction">
下一页
</span>
<div class="md-ellipsis">
13.1. &nbsp; 初探动态规划New
14.1. &nbsp; 初探动态规划New
</div>
</div>
<div class="md-footer__button md-icon">

View File

@@ -25,7 +25,7 @@
<title>13.1.   初探动态规划New - Hello 算法</title>
<title>14.1.   初探动态规划New - Hello 算法</title>
@@ -79,7 +79,7 @@
<div data-md-component="skip">
<a href="#131" class="md-skip">
<a href="#141" class="md-skip">
跳转至
</a>
@@ -113,7 +113,7 @@
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
13.1. &nbsp; 初探动态规划New
14.1. &nbsp; 初探动态规划New
</span>
</div>
@@ -1771,6 +1771,87 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../../chapter_divide_and_conquer/">12. &nbsp; &nbsp; 分治</a>
<label for="__nav_13">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_13">
<span class="md-nav__icon md-icon"></span>
12. &nbsp; &nbsp; 分治
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_divide_and_conquer/divide_and_conquer/" class="md-nav__link">
12.1. &nbsp; 分治算法New
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_divide_and_conquer/build_binary_tree/" class="md-nav__link">
12.2. &nbsp; 构建树问题New
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_14" >
@@ -1782,18 +1863,18 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../../chapter_backtracking/">12. &nbsp; &nbsp; 回溯</a>
<a href="../../chapter_backtracking/">13. &nbsp; &nbsp; 回溯</a>
<label for="__nav_13">
<label for="__nav_14">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_13">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_14_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_14">
<span class="md-nav__icon md-icon"></span>
12. &nbsp; &nbsp; 回溯
13. &nbsp; &nbsp; 回溯
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -1806,7 +1887,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/backtracking_algorithm/" class="md-nav__link">
12.1. &nbsp; 回溯算法
13.1. &nbsp; 回溯算法
</a>
</li>
@@ -1820,7 +1901,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/permutations_problem/" class="md-nav__link">
12.2. &nbsp; 全排列问题
13.2. &nbsp; 全排列问题
</a>
</li>
@@ -1834,7 +1915,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/subset_sum_problem/" class="md-nav__link">
12.3. &nbsp; 子集和问题
13.3. &nbsp; 子集和问题
</a>
</li>
@@ -1848,7 +1929,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/n_queens_problem/" class="md-nav__link">
12.4. &nbsp; N 皇后问题
13.4. &nbsp; N 皇后问题
</a>
</li>
@@ -1862,7 +1943,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/summary/" class="md-nav__link">
12.5. &nbsp; 小结
13.5. &nbsp; 小结
</a>
</li>
@@ -1890,7 +1971,7 @@
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_14" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_15" checked>
@@ -1917,18 +1998,18 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../">13. &nbsp; &nbsp; 动态规划</a>
<a href="../">14. &nbsp; &nbsp; 动态规划</a>
<label for="__nav_14">
<label for="__nav_15">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_14_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_14">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_15_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_15">
<span class="md-nav__icon md-icon"></span>
13. &nbsp; &nbsp; 动态规划
14. &nbsp; &nbsp; 动态规划
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -1950,12 +2031,12 @@
<label class="md-nav__link md-nav__link--active" for="__toc">
13.1. &nbsp; 初探动态规划New
14.1. &nbsp; 初探动态规划New
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
13.1. &nbsp; 初探动态规划New
14.1. &nbsp; 初探动态规划New
</a>
@@ -1974,22 +2055,22 @@
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#1311" class="md-nav__link">
13.1.1. &nbsp; 方法一:暴力搜索
<a href="#1411" class="md-nav__link">
14.1.1. &nbsp; 方法一:暴力搜索
</a>
</li>
<li class="md-nav__item">
<a href="#1312" class="md-nav__link">
13.1.2. &nbsp; 方法二:记忆化搜索
<a href="#1412" class="md-nav__link">
14.1.2. &nbsp; 方法二:记忆化搜索
</a>
</li>
<li class="md-nav__item">
<a href="#1313" class="md-nav__link">
13.1.3. &nbsp; 方法三:动态规划
<a href="#1413" class="md-nav__link">
14.1.3. &nbsp; 方法三:动态规划
</a>
</li>
@@ -2010,7 +2091,7 @@
<li class="md-nav__item">
<a href="../dp_problem_features/" class="md-nav__link">
13.2. &nbsp; DP 问题特性New
14.2. &nbsp; DP 问题特性New
</a>
</li>
@@ -2024,7 +2105,7 @@
<li class="md-nav__item">
<a href="../dp_solution_pipeline/" class="md-nav__link">
13.3. &nbsp; DP 解题思路New
14.3. &nbsp; DP 解题思路New
</a>
</li>
@@ -2038,7 +2119,7 @@
<li class="md-nav__item">
<a href="../knapsack_problem/" class="md-nav__link">
13.4. &nbsp; 0-1 背包问题New
14.4. &nbsp; 0-1 背包问题New
</a>
</li>
@@ -2052,7 +2133,7 @@
<li class="md-nav__item">
<a href="../unbounded_knapsack_problem/" class="md-nav__link">
13.5. &nbsp; 完全背包问题New
14.5. &nbsp; 完全背包问题New
</a>
</li>
@@ -2066,7 +2147,7 @@
<li class="md-nav__item">
<a href="../edit_distance_problem/" class="md-nav__link">
13.6. &nbsp; 编辑距离问题New
14.6. &nbsp; 编辑距离问题New
</a>
</li>
@@ -2080,76 +2161,7 @@
<li class="md-nav__item">
<a href="../summary/" class="md-nav__link">
13.7. &nbsp; 小结New
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_15" >
<label class="md-nav__link" for="__nav_15" id="__nav_15_label" tabindex="0">
14. &nbsp; &nbsp; 附录
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_15_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_15">
<span class="md-nav__icon md-icon"></span>
14. &nbsp; &nbsp; 附录
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_appendix/installation/" class="md-nav__link">
14.1. &nbsp; 编程环境安装
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_appendix/contribution/" class="md-nav__link">
14.2. &nbsp; 一起参与创作
14.7. &nbsp; 小结New
</a>
</li>
@@ -2180,6 +2192,75 @@
<label class="md-nav__link" for="__nav_16" id="__nav_16_label" tabindex="0">
15. &nbsp; &nbsp; 附录
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_16_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_16">
<span class="md-nav__icon md-icon"></span>
15. &nbsp; &nbsp; 附录
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_appendix/installation/" class="md-nav__link">
15.1. &nbsp; 编程环境安装
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_appendix/contribution/" class="md-nav__link">
15.2. &nbsp; 一起参与创作
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_17" >
@@ -2192,8 +2273,8 @@
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_16_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_16">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_17_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_17">
<span class="md-nav__icon md-icon"></span>
参考文献
</label>
@@ -2234,22 +2315,22 @@
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#1311" class="md-nav__link">
13.1.1. &nbsp; 方法一:暴力搜索
<a href="#1411" class="md-nav__link">
14.1.1. &nbsp; 方法一:暴力搜索
</a>
</li>
<li class="md-nav__item">
<a href="#1312" class="md-nav__link">
13.1.2. &nbsp; 方法二:记忆化搜索
<a href="#1412" class="md-nav__link">
14.1.2. &nbsp; 方法二:记忆化搜索
</a>
</li>
<li class="md-nav__item">
<a href="#1313" class="md-nav__link">
13.1.3. &nbsp; 方法三:动态规划
<a href="#1413" class="md-nav__link">
14.1.3. &nbsp; 方法三:动态规划
</a>
</li>
@@ -2277,7 +2358,7 @@
<h1 id="131">13.1. &nbsp; 初探动态规划<a class="headerlink" href="#131" title="Permanent link">&para;</a></h1>
<h1 id="141">14.1. &nbsp; 初探动态规划<a class="headerlink" href="#141" title="Permanent link">&para;</a></h1>
<p>「动态规划 Dynamic Programming」是一种通过将复杂问题分解为更简单的子问题的方式来求解问题的方法。它将一个问题分解为一系列更小的子问题并通过存储子问题的解来避免重复计算从而大幅提升时间效率。</p>
<p>在本节中,我们从一个经典例题入手,先给出它的暴力回溯解法,观察其中包含的重叠子问题,再逐步导出更高效的动态规划解法。</p>
<div class="admonition question">
@@ -2428,9 +2509,25 @@
</code></pre></div>
</div>
<div class="tabbed-block">
<div class="highlight"><span class="filename">climbing_stairs_backtrack.zig</span><pre><span></span><code><a id="__codelineno-9-1" name="__codelineno-9-1" href="#__codelineno-9-1"></a><span class="p">[</span><span class="n">class</span><span class="p">]{}</span><span class="o">-</span><span class="p">[</span><span class="n">func</span><span class="p">]{</span><span class="n">backtrack</span><span class="p">}</span>
<a id="__codelineno-9-2" name="__codelineno-9-2" href="#__codelineno-9-2"></a>
<a id="__codelineno-9-3" name="__codelineno-9-3" href="#__codelineno-9-3"></a><span class="p">[</span><span class="n">class</span><span class="p">]{}</span><span class="o">-</span><span class="p">[</span><span class="n">func</span><span class="p">]{</span><span class="n">climbingStairsBacktrack</span><span class="p">}</span>
<div class="highlight"><span class="filename">climbing_stairs_backtrack.zig</span><pre><span></span><code><a id="__codelineno-9-1" name="__codelineno-9-1" href="#__codelineno-9-1"></a><span class="c1">// 回溯</span>
<a id="__codelineno-9-2" name="__codelineno-9-2" href="#__codelineno-9-2"></a><span class="k">fn</span><span class="w"> </span><span class="n">backtrack</span><span class="p">(</span><span class="n">choices</span><span class="o">:</span><span class="w"> </span><span class="p">[]</span><span class="kt">i32</span><span class="p">,</span><span class="w"> </span><span class="n">state</span><span class="o">:</span><span class="w"> </span><span class="kt">i32</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="o">:</span><span class="w"> </span><span class="kt">i32</span><span class="p">,</span><span class="w"> </span><span class="n">res</span><span class="o">:</span><span class="w"> </span><span class="n">std</span><span class="p">.</span><span class="n">ArrayList</span><span class="p">(</span><span class="kt">i32</span><span class="p">))</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-9-3" name="__codelineno-9-3" href="#__codelineno-9-3"></a><span class="w"> </span><span class="c1">// 当爬到第 n 阶时,方案数量加 1</span>
<a id="__codelineno-9-4" name="__codelineno-9-4" href="#__codelineno-9-4"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">state</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">n</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-9-5" name="__codelineno-9-5" href="#__codelineno-9-5"></a><span class="w"> </span><span class="n">res</span><span class="p">.</span><span class="n">items</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">res</span><span class="p">.</span><span class="n">items</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<a id="__codelineno-9-6" name="__codelineno-9-6" href="#__codelineno-9-6"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-9-7" name="__codelineno-9-7" href="#__codelineno-9-7"></a><span class="w"> </span><span class="c1">// 遍历所有选择</span>
<a id="__codelineno-9-8" name="__codelineno-9-8" href="#__codelineno-9-8"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">choices</span><span class="p">)</span><span class="w"> </span><span class="o">|</span><span class="n">choice</span><span class="o">|</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-9-9" name="__codelineno-9-9" href="#__codelineno-9-9"></a><span class="w"> </span><span class="c1">// 剪枝:不允许越过第 n 阶</span>
<a id="__codelineno-9-10" name="__codelineno-9-10" href="#__codelineno-9-10"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">state</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">choice</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">n</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-9-11" name="__codelineno-9-11" href="#__codelineno-9-11"></a><span class="w"> </span><span class="k">break</span><span class="p">;</span>
<a id="__codelineno-9-12" name="__codelineno-9-12" href="#__codelineno-9-12"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-9-13" name="__codelineno-9-13" href="#__codelineno-9-13"></a><span class="w"> </span><span class="c1">// 尝试:做出选择,更新状态</span>
<a id="__codelineno-9-14" name="__codelineno-9-14" href="#__codelineno-9-14"></a><span class="w"> </span><span class="n">backtrack</span><span class="p">(</span><span class="n">choices</span><span class="p">,</span><span class="w"> </span><span class="n">state</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">choice</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="n">res</span><span class="p">);</span>
<a id="__codelineno-9-15" name="__codelineno-9-15" href="#__codelineno-9-15"></a><span class="w"> </span><span class="c1">// 回退</span>
<a id="__codelineno-9-16" name="__codelineno-9-16" href="#__codelineno-9-16"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-9-17" name="__codelineno-9-17" href="#__codelineno-9-17"></a><span class="p">}</span>
<a id="__codelineno-9-18" name="__codelineno-9-18" href="#__codelineno-9-18"></a>
<a id="__codelineno-9-19" name="__codelineno-9-19" href="#__codelineno-9-19"></a><span class="p">[</span><span class="n">class</span><span class="p">]{}</span><span class="o">-</span><span class="p">[</span><span class="n">func</span><span class="p">]{</span><span class="n">climbingStairsBacktrack</span><span class="p">}</span>
</code></pre></div>
</div>
<div class="tabbed-block">
@@ -2441,7 +2538,7 @@
</div>
</div>
</div>
<h2 id="1311">13.1.1. &nbsp; 方法一:暴力搜索<a class="headerlink" href="#1311" title="Permanent link">&para;</a></h2>
<h2 id="1411">14.1.1. &nbsp; 方法一:暴力搜索<a class="headerlink" href="#1411" title="Permanent link">&para;</a></h2>
<p>回溯算法通常并不显式地对问题进行拆解,而是将问题看作一系列决策步骤,通过试探和剪枝,搜索所有可能的解。</p>
<p>对于本题,我们可以尝试将问题拆解为更小的子问题。设爬到第 <span class="arithmatex">\(i\)</span> 阶共有 <span class="arithmatex">\(dp[i]\)</span> 种方案,那么 <span class="arithmatex">\(dp[i]\)</span> 就是原问题,其子问题包括:</p>
<div class="arithmatex">\[
@@ -2557,9 +2654,18 @@ dp[i] = dp[i-1] + dp[i-2]
</code></pre></div>
</div>
<div class="tabbed-block">
<div class="highlight"><span class="filename">climbing_stairs_dfs.zig</span><pre><span></span><code><a id="__codelineno-20-1" name="__codelineno-20-1" href="#__codelineno-20-1"></a><span class="p">[</span><span class="n">class</span><span class="p">]{}</span><span class="o">-</span><span class="p">[</span><span class="n">func</span><span class="p">]{</span><span class="n">dfs</span><span class="p">}</span>
<a id="__codelineno-20-2" name="__codelineno-20-2" href="#__codelineno-20-2"></a>
<a id="__codelineno-20-3" name="__codelineno-20-3" href="#__codelineno-20-3"></a><span class="p">[</span><span class="n">class</span><span class="p">]{}</span><span class="o">-</span><span class="p">[</span><span class="n">func</span><span class="p">]{</span><span class="n">climbingStairsDFS</span><span class="p">}</span>
<div class="highlight"><span class="filename">climbing_stairs_dfs.zig</span><pre><span></span><code><a id="__codelineno-20-1" name="__codelineno-20-1" href="#__codelineno-20-1"></a><span class="c1">// 搜索</span>
<a id="__codelineno-20-2" name="__codelineno-20-2" href="#__codelineno-20-2"></a><span class="k">fn</span><span class="w"> </span><span class="n">dfs</span><span class="p">(</span><span class="n">i</span><span class="o">:</span><span class="w"> </span><span class="kt">usize</span><span class="p">)</span><span class="w"> </span><span class="kt">i32</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-20-3" name="__codelineno-20-3" href="#__codelineno-20-3"></a><span class="w"> </span><span class="c1">// 已知 dp[1] 和 dp[2] ,返回之</span>
<a id="__codelineno-20-4" name="__codelineno-20-4" href="#__codelineno-20-4"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="k">or</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-20-5" name="__codelineno-20-5" href="#__codelineno-20-5"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">@intCast</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
<a id="__codelineno-20-6" name="__codelineno-20-6" href="#__codelineno-20-6"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-20-7" name="__codelineno-20-7" href="#__codelineno-20-7"></a><span class="w"> </span><span class="c1">// dp[i] = dp[i-1] + dp[i-2]</span>
<a id="__codelineno-20-8" name="__codelineno-20-8" href="#__codelineno-20-8"></a><span class="w"> </span><span class="kr">var</span><span class="w"> </span><span class="n">count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">dfs</span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">dfs</span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">2</span><span class="p">);</span>
<a id="__codelineno-20-9" name="__codelineno-20-9" href="#__codelineno-20-9"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">count</span><span class="p">;</span>
<a id="__codelineno-20-10" name="__codelineno-20-10" href="#__codelineno-20-10"></a><span class="p">}</span>
<a id="__codelineno-20-11" name="__codelineno-20-11" href="#__codelineno-20-11"></a>
<a id="__codelineno-20-12" name="__codelineno-20-12" href="#__codelineno-20-12"></a><span class="p">[</span><span class="n">class</span><span class="p">]{}</span><span class="o">-</span><span class="p">[</span><span class="n">func</span><span class="p">]{</span><span class="n">climbingStairsDFS</span><span class="p">}</span>
</code></pre></div>
</div>
<div class="tabbed-block">
@@ -2575,7 +2681,7 @@ dp[i] = dp[i-1] + dp[i-2]
<p align="center"> Fig. 爬楼梯对应递归树 </p>
<p>实际上,<strong>指数阶的时间复杂度是由于「重叠子问题」导致的</strong>。例如,问题 <span class="arithmatex">\(dp[9]\)</span> 被分解为子问题 <span class="arithmatex">\(dp[8]\)</span><span class="arithmatex">\(dp[7]\)</span> ,问题 <span class="arithmatex">\(dp[8]\)</span> 被分解为子问题 <span class="arithmatex">\(dp[7]\)</span><span class="arithmatex">\(dp[6]\)</span> ,两者都包含子问题 <span class="arithmatex">\(dp[7]\)</span> ,而子问题中又包含更小的重叠子问题,子子孙孙无穷尽也,绝大部分计算资源都浪费在这些重叠的问题上。</p>
<h2 id="1312">13.1.2. &nbsp; 方法二:记忆化搜索<a class="headerlink" href="#1312" title="Permanent link">&para;</a></h2>
<h2 id="1412">14.1.2. &nbsp; 方法二:记忆化搜索<a class="headerlink" href="#1412" title="Permanent link">&para;</a></h2>
<p>为了提升算法效率,<strong>我们希望所有的重叠子问题都只被计算一次</strong>。具体来说,考虑借助一个数组 <code>mem</code> 来记录每个子问题的解,并在搜索过程中这样做:</p>
<ul>
<li>当首次计算 <span class="arithmatex">\(dp[i]\)</span> 时,我们将其记录至 <code>mem[i]</code> ,以便之后使用;</li>
@@ -2710,9 +2816,24 @@ dp[i] = dp[i-1] + dp[i-2]
</code></pre></div>
</div>
<div class="tabbed-block">
<div class="highlight"><span class="filename">climbing_stairs_dfs_mem.zig</span><pre><span></span><code><a id="__codelineno-31-1" name="__codelineno-31-1" href="#__codelineno-31-1"></a><span class="p">[</span><span class="n">class</span><span class="p">]{}</span><span class="o">-</span><span class="p">[</span><span class="n">func</span><span class="p">]{</span><span class="n">dfs</span><span class="p">}</span>
<a id="__codelineno-31-2" name="__codelineno-31-2" href="#__codelineno-31-2"></a>
<a id="__codelineno-31-3" name="__codelineno-31-3" href="#__codelineno-31-3"></a><span class="p">[</span><span class="n">class</span><span class="p">]{}</span><span class="o">-</span><span class="p">[</span><span class="n">func</span><span class="p">]{</span><span class="n">climbingStairsDFSMem</span><span class="p">}</span>
<div class="highlight"><span class="filename">climbing_stairs_dfs_mem.zig</span><pre><span></span><code><a id="__codelineno-31-1" name="__codelineno-31-1" href="#__codelineno-31-1"></a><span class="c1">// 记忆化搜索</span>
<a id="__codelineno-31-2" name="__codelineno-31-2" href="#__codelineno-31-2"></a><span class="k">fn</span><span class="w"> </span><span class="n">dfs</span><span class="p">(</span><span class="n">i</span><span class="o">:</span><span class="w"> </span><span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="n">mem</span><span class="o">:</span><span class="w"> </span><span class="p">[]</span><span class="kt">i32</span><span class="p">)</span><span class="w"> </span><span class="kt">i32</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-31-3" name="__codelineno-31-3" href="#__codelineno-31-3"></a><span class="w"> </span><span class="c1">// 已知 dp[1] 和 dp[2] ,返回之</span>
<a id="__codelineno-31-4" name="__codelineno-31-4" href="#__codelineno-31-4"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="k">or</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-31-5" name="__codelineno-31-5" href="#__codelineno-31-5"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">@intCast</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
<a id="__codelineno-31-6" name="__codelineno-31-6" href="#__codelineno-31-6"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-31-7" name="__codelineno-31-7" href="#__codelineno-31-7"></a><span class="w"> </span><span class="c1">// 若存在记录 dp[i] ,则直接返回之</span>
<a id="__codelineno-31-8" name="__codelineno-31-8" href="#__codelineno-31-8"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">mem</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-31-9" name="__codelineno-31-9" href="#__codelineno-31-9"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">mem</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
<a id="__codelineno-31-10" name="__codelineno-31-10" href="#__codelineno-31-10"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-31-11" name="__codelineno-31-11" href="#__codelineno-31-11"></a><span class="w"> </span><span class="c1">// dp[i] = dp[i-1] + dp[i-2]</span>
<a id="__codelineno-31-12" name="__codelineno-31-12" href="#__codelineno-31-12"></a><span class="w"> </span><span class="kr">var</span><span class="w"> </span><span class="n">count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">dfs</span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">mem</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">dfs</span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="n">mem</span><span class="p">);</span>
<a id="__codelineno-31-13" name="__codelineno-31-13" href="#__codelineno-31-13"></a><span class="w"> </span><span class="c1">// 记录 dp[i]</span>
<a id="__codelineno-31-14" name="__codelineno-31-14" href="#__codelineno-31-14"></a><span class="w"> </span><span class="n">mem</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">count</span><span class="p">;</span>
<a id="__codelineno-31-15" name="__codelineno-31-15" href="#__codelineno-31-15"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">count</span><span class="p">;</span>
<a id="__codelineno-31-16" name="__codelineno-31-16" href="#__codelineno-31-16"></a><span class="p">}</span>
<a id="__codelineno-31-17" name="__codelineno-31-17" href="#__codelineno-31-17"></a>
<a id="__codelineno-31-18" name="__codelineno-31-18" href="#__codelineno-31-18"></a><span class="p">[</span><span class="n">class</span><span class="p">]{}</span><span class="o">-</span><span class="p">[</span><span class="n">func</span><span class="p">]{</span><span class="n">climbingStairsDFSMem</span><span class="p">}</span>
</code></pre></div>
</div>
<div class="tabbed-block">
@@ -2727,7 +2848,7 @@ dp[i] = dp[i-1] + dp[i-2]
<p><img alt="记忆化搜索对应递归树" src="../intro_to_dynamic_programming.assets/climbing_stairs_dfs_memo_tree.png" /></p>
<p align="center"> Fig. 记忆化搜索对应递归树 </p>
<h2 id="1313">13.1.3. &nbsp; 方法三:动态规划<a class="headerlink" href="#1313" title="Permanent link">&para;</a></h2>
<h2 id="1413">14.1.3. &nbsp; 方法三:动态规划<a class="headerlink" href="#1413" title="Permanent link">&para;</a></h2>
<p><strong>记忆化搜索是一种“从顶至底”的方法</strong>:我们从原问题(根节点)开始,递归地将较大子问题分解为较小子问题,直至解已知的最小子问题(叶节点);最终通过回溯将子问题的解逐层收集,得到原问题的解。</p>
<p><strong>我们也可以直接“从底至顶”进行求解</strong>,得到标准的动态规划解法:从最小子问题开始,迭代地求解较大子问题,直至得到原问题的解。</p>
<p>由于动态规划不包含回溯过程,因此无需使用递归,而可以直接基于递推实现。我们初始化一个数组 <code>dp</code> 来存储子问题的解,从最小子问题开始,逐步求解较大子问题。在以下代码中,数组 <code>dp</code> 起到了记忆化搜索中数组 <code>mem</code> 相同的记录作用。</p>
@@ -2934,8 +3055,8 @@ dp[i] = dp[i-1] + dp[i-2]
<p>总的看来,<strong>子问题分解是一种通用的算法思路,在分治、动态规划、回溯中各有特点</strong></p>
<ul>
<li>分治算法将原问题划分为几个独立的子问题,然后递归解决子问题,最后合并子问题的解得到原问题的解。例如,归并排序将长数组不断划分为两个短子数组,再将排序好的子数组合并为排序好的长数组。</li>
<li>动态规划也是将原问题分解为多个子问题,但与分治算法的主要区别是,<strong>动态规划中的子问题往往不是相互独立的</strong>,原问题的解依赖于子问题的解,而子问题的解又依赖于更小的子问题的解。因此,动态规划通常会引入记忆化,保存已经解决的子问题的解,避免重复计算。</li>
<li>回溯算法在尝试和回退中穷举所有可能的解,并通过剪枝避免不必要的搜索分支。原问题的解由一系列决策步骤构成,我们可以将每个决策步骤之后的剩余问题看作为一个子问题。</li>
<li>动态规划也是将原问题分解为多个子问题,但与分治算法的主要区别是,<strong>动态规划中的子问题往往不是相互独立的</strong>,原问题的解依赖于子问题的解,而子问题的解又依赖于更小的子问题的解。</li>
<li>回溯算法在尝试和回退中穷举所有可能的解,并通过剪枝避免不必要的搜索分支。原问题的解由一系列决策步骤构成,我们可以将每个决策步骤之前的子序列看作为一个子问题。</li>
</ul>
@@ -3014,7 +3135,7 @@ dp[i] = dp[i-1] + dp[i-2]
<nav class="md-footer__inner md-grid" aria-label="页脚" >
<a href="../" class="md-footer__link md-footer__link--prev" aria-label="上一页: 13. &amp;nbsp; 动态规划" rel="prev">
<a href="../" class="md-footer__link md-footer__link--prev" aria-label="上一页: 14. &amp;nbsp; 动态规划" rel="prev">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</div>
@@ -3023,20 +3144,20 @@ dp[i] = dp[i-1] + dp[i-2]
上一页
</span>
<div class="md-ellipsis">
13. &nbsp; 动态规划
14. &nbsp; 动态规划
</div>
</div>
</a>
<a href="../dp_problem_features/" class="md-footer__link md-footer__link--next" aria-label="下一页: 13.2. &amp;nbsp; DP 问题特性New" rel="next">
<a href="../dp_problem_features/" class="md-footer__link md-footer__link--next" aria-label="下一页: 14.2. &amp;nbsp; DP 问题特性New" rel="next">
<div class="md-footer__title">
<span class="md-footer__direction">
下一页
</span>
<div class="md-ellipsis">
13.2. &nbsp; DP 问题特性New
14.2. &nbsp; DP 问题特性New
</div>
</div>
<div class="md-footer__button md-icon">

View File

@@ -25,7 +25,7 @@
<title>13.4.   0-1 背包问题New - Hello 算法</title>
<title>14.4.   0-1 背包问题New - Hello 算法</title>
@@ -79,7 +79,7 @@
<div data-md-component="skip">
<a href="#134-0-1" class="md-skip">
<a href="#144-0-1" class="md-skip">
跳转至
</a>
@@ -113,7 +113,7 @@
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
13.4. &nbsp; 0-1 背包问题New
14.4. &nbsp; 0-1 背包问题New
</span>
</div>
@@ -1771,6 +1771,87 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../../chapter_divide_and_conquer/">12. &nbsp; &nbsp; 分治</a>
<label for="__nav_13">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_13">
<span class="md-nav__icon md-icon"></span>
12. &nbsp; &nbsp; 分治
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_divide_and_conquer/divide_and_conquer/" class="md-nav__link">
12.1. &nbsp; 分治算法New
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_divide_and_conquer/build_binary_tree/" class="md-nav__link">
12.2. &nbsp; 构建树问题New
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_14" >
@@ -1782,18 +1863,18 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../../chapter_backtracking/">12. &nbsp; &nbsp; 回溯</a>
<a href="../../chapter_backtracking/">13. &nbsp; &nbsp; 回溯</a>
<label for="__nav_13">
<label for="__nav_14">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_13">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_14_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_14">
<span class="md-nav__icon md-icon"></span>
12. &nbsp; &nbsp; 回溯
13. &nbsp; &nbsp; 回溯
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -1806,7 +1887,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/backtracking_algorithm/" class="md-nav__link">
12.1. &nbsp; 回溯算法
13.1. &nbsp; 回溯算法
</a>
</li>
@@ -1820,7 +1901,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/permutations_problem/" class="md-nav__link">
12.2. &nbsp; 全排列问题
13.2. &nbsp; 全排列问题
</a>
</li>
@@ -1834,7 +1915,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/subset_sum_problem/" class="md-nav__link">
12.3. &nbsp; 子集和问题
13.3. &nbsp; 子集和问题
</a>
</li>
@@ -1848,7 +1929,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/n_queens_problem/" class="md-nav__link">
12.4. &nbsp; N 皇后问题
13.4. &nbsp; N 皇后问题
</a>
</li>
@@ -1862,7 +1943,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/summary/" class="md-nav__link">
12.5. &nbsp; 小结
13.5. &nbsp; 小结
</a>
</li>
@@ -1890,7 +1971,7 @@
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_14" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_15" checked>
@@ -1917,18 +1998,18 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../">13. &nbsp; &nbsp; 动态规划</a>
<a href="../">14. &nbsp; &nbsp; 动态规划</a>
<label for="__nav_14">
<label for="__nav_15">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_14_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_14">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_15_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_15">
<span class="md-nav__icon md-icon"></span>
13. &nbsp; &nbsp; 动态规划
14. &nbsp; &nbsp; 动态规划
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -1941,7 +2022,7 @@
<li class="md-nav__item">
<a href="../intro_to_dynamic_programming/" class="md-nav__link">
13.1. &nbsp; 初探动态规划New
14.1. &nbsp; 初探动态规划New
</a>
</li>
@@ -1955,7 +2036,7 @@
<li class="md-nav__item">
<a href="../dp_problem_features/" class="md-nav__link">
13.2. &nbsp; DP 问题特性New
14.2. &nbsp; DP 问题特性New
</a>
</li>
@@ -1969,7 +2050,7 @@
<li class="md-nav__item">
<a href="../dp_solution_pipeline/" class="md-nav__link">
13.3. &nbsp; DP 解题思路New
14.3. &nbsp; DP 解题思路New
</a>
</li>
@@ -1992,12 +2073,12 @@
<label class="md-nav__link md-nav__link--active" for="__toc">
13.4. &nbsp; 0-1 背包问题New
14.4. &nbsp; 0-1 背包问题New
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
13.4. &nbsp; 0-1 背包问题New
14.4. &nbsp; 0-1 背包问题New
</a>
@@ -2016,22 +2097,22 @@
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#1341" class="md-nav__link">
13.4.1. &nbsp; 方法一:暴力搜索
<a href="#1441" class="md-nav__link">
14.4.1. &nbsp; 方法一:暴力搜索
</a>
</li>
<li class="md-nav__item">
<a href="#1342" class="md-nav__link">
13.4.2. &nbsp; 方法二:记忆化搜索
<a href="#1442" class="md-nav__link">
14.4.2. &nbsp; 方法二:记忆化搜索
</a>
</li>
<li class="md-nav__item">
<a href="#1343" class="md-nav__link">
13.4.3. &nbsp; 方法三:动态规划
<a href="#1443" class="md-nav__link">
14.4.3. &nbsp; 方法三:动态规划
</a>
</li>
@@ -2052,7 +2133,7 @@
<li class="md-nav__item">
<a href="../unbounded_knapsack_problem/" class="md-nav__link">
13.5. &nbsp; 完全背包问题New
14.5. &nbsp; 完全背包问题New
</a>
</li>
@@ -2066,7 +2147,7 @@
<li class="md-nav__item">
<a href="../edit_distance_problem/" class="md-nav__link">
13.6. &nbsp; 编辑距离问题New
14.6. &nbsp; 编辑距离问题New
</a>
</li>
@@ -2080,76 +2161,7 @@
<li class="md-nav__item">
<a href="../summary/" class="md-nav__link">
13.7. &nbsp; 小结New
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_15" >
<label class="md-nav__link" for="__nav_15" id="__nav_15_label" tabindex="0">
14. &nbsp; &nbsp; 附录
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_15_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_15">
<span class="md-nav__icon md-icon"></span>
14. &nbsp; &nbsp; 附录
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_appendix/installation/" class="md-nav__link">
14.1. &nbsp; 编程环境安装
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_appendix/contribution/" class="md-nav__link">
14.2. &nbsp; 一起参与创作
14.7. &nbsp; 小结New
</a>
</li>
@@ -2180,6 +2192,75 @@
<label class="md-nav__link" for="__nav_16" id="__nav_16_label" tabindex="0">
15. &nbsp; &nbsp; 附录
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_16_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_16">
<span class="md-nav__icon md-icon"></span>
15. &nbsp; &nbsp; 附录
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_appendix/installation/" class="md-nav__link">
15.1. &nbsp; 编程环境安装
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_appendix/contribution/" class="md-nav__link">
15.2. &nbsp; 一起参与创作
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_17" >
@@ -2192,8 +2273,8 @@
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_16_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_16">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_17_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_17">
<span class="md-nav__icon md-icon"></span>
参考文献
</label>
@@ -2234,22 +2315,22 @@
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#1341" class="md-nav__link">
13.4.1. &nbsp; 方法一:暴力搜索
<a href="#1441" class="md-nav__link">
14.4.1. &nbsp; 方法一:暴力搜索
</a>
</li>
<li class="md-nav__item">
<a href="#1342" class="md-nav__link">
13.4.2. &nbsp; 方法二:记忆化搜索
<a href="#1442" class="md-nav__link">
14.4.2. &nbsp; 方法二:记忆化搜索
</a>
</li>
<li class="md-nav__item">
<a href="#1343" class="md-nav__link">
13.4.3. &nbsp; 方法三:动态规划
<a href="#1443" class="md-nav__link">
14.4.3. &nbsp; 方法三:动态规划
</a>
</li>
@@ -2277,7 +2358,7 @@
<h1 id="134-0-1">13.4. &nbsp; 0-1 背包问题<a class="headerlink" href="#134-0-1" title="Permanent link">&para;</a></h1>
<h1 id="144-0-1">14.4. &nbsp; 0-1 背包问题<a class="headerlink" href="#144-0-1" title="Permanent link">&para;</a></h1>
<p>背包问题是一个非常好的动态规划入门题目,是动态规划中最常见的问题形式。其具有很多变种,例如 0-1 背包问题、完全背包问题、多重背包问题等。</p>
<p>在本节中,我们先来学习基础的的 0-1 背包问题。</p>
<div class="admonition question">
@@ -2312,7 +2393,7 @@ dp[i, c] = \max(dp[i-1, c], dp[i-1, c - wgt[i-1]] + val[i-1])
<p class="admonition-title">Tip</p>
<p>完成以上三步后,我们可以直接实现从底至顶的动态规划解法。而为了展示本题包含的重叠子问题,本文也同时给出从顶至底的暴力搜索和记忆化搜索解法。</p>
</div>
<h2 id="1341">13.4.1. &nbsp; 方法一:暴力搜索<a class="headerlink" href="#1341" title="Permanent link">&para;</a></h2>
<h2 id="1441">14.4.1. &nbsp; 方法一:暴力搜索<a class="headerlink" href="#1441" title="Permanent link">&para;</a></h2>
<p>搜索代码包含以下要素:</p>
<ul>
<li><strong>递归参数</strong>:状态 <span class="arithmatex">\([i, c]\)</span> <strong>返回值</strong>:子问题的解 <span class="arithmatex">\(dp[i, c]\)</span></li>
@@ -2429,7 +2510,7 @@ dp[i, c] = \max(dp[i-1, c], dp[i-1, c - wgt[i-1]] + val[i-1])
<p><img alt="0-1 背包的暴力搜索递归树" src="../knapsack_problem.assets/knapsack_dfs.png" /></p>
<p align="center"> Fig. 0-1 背包的暴力搜索递归树 </p>
<h2 id="1342">13.4.2. &nbsp; 方法二:记忆化搜索<a class="headerlink" href="#1342" title="Permanent link">&para;</a></h2>
<h2 id="1442">14.4.2. &nbsp; 方法二:记忆化搜索<a class="headerlink" href="#1442" title="Permanent link">&para;</a></h2>
<p>为了防止重复求解重叠子问题,我们借助一个记忆列表 <code>mem</code> 来记录子问题的解,其中 <code>mem[i][c]</code> 对应解 <span class="arithmatex">\(dp[i, c]\)</span></p>
<div class="tabbed-set tabbed-alternate" data-tabs="2:11"><input checked="checked" id="__tabbed_2_1" name="__tabbed_2" type="radio" /><input id="__tabbed_2_2" name="__tabbed_2" type="radio" /><input id="__tabbed_2_3" name="__tabbed_2" type="radio" /><input id="__tabbed_2_4" name="__tabbed_2" type="radio" /><input id="__tabbed_2_5" name="__tabbed_2" type="radio" /><input id="__tabbed_2_6" name="__tabbed_2" type="radio" /><input id="__tabbed_2_7" name="__tabbed_2" type="radio" /><input id="__tabbed_2_8" name="__tabbed_2" type="radio" /><input id="__tabbed_2_9" name="__tabbed_2" type="radio" /><input id="__tabbed_2_10" name="__tabbed_2" type="radio" /><input id="__tabbed_2_11" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="__tabbed_2_1">Java</label><label for="__tabbed_2_2">C++</label><label for="__tabbed_2_3">Python</label><label for="__tabbed_2_4">Go</label><label for="__tabbed_2_5">JavaScript</label><label for="__tabbed_2_6">TypeScript</label><label for="__tabbed_2_7">C</label><label for="__tabbed_2_8">C#</label><label for="__tabbed_2_9">Swift</label><label for="__tabbed_2_10">Zig</label><label for="__tabbed_2_11">Dart</label></div>
<div class="tabbed-content">
@@ -2561,7 +2642,7 @@ dp[i, c] = \max(dp[i-1, c], dp[i-1, c - wgt[i-1]] + val[i-1])
<p><img alt="0-1 背包的记忆化搜索递归树" src="../knapsack_problem.assets/knapsack_dfs_mem.png" /></p>
<p align="center"> Fig. 0-1 背包的记忆化搜索递归树 </p>
<h2 id="1343">13.4.3. &nbsp; 方法三:动态规划<a class="headerlink" href="#1343" title="Permanent link">&para;</a></h2>
<h2 id="1443">14.4.3. &nbsp; 方法三:动态规划<a class="headerlink" href="#1443" title="Permanent link">&para;</a></h2>
<p>动态规划解法本质上就是在状态转移中填充 <span class="arithmatex">\(dp\)</span> 表的过程,代码如下所示。</p>
<div class="tabbed-set tabbed-alternate" data-tabs="3:11"><input checked="checked" id="__tabbed_3_1" name="__tabbed_3" type="radio" /><input id="__tabbed_3_2" name="__tabbed_3" type="radio" /><input id="__tabbed_3_3" name="__tabbed_3" type="radio" /><input id="__tabbed_3_4" name="__tabbed_3" type="radio" /><input id="__tabbed_3_5" name="__tabbed_3" type="radio" /><input id="__tabbed_3_6" name="__tabbed_3" type="radio" /><input id="__tabbed_3_7" name="__tabbed_3" type="radio" /><input id="__tabbed_3_8" name="__tabbed_3" type="radio" /><input id="__tabbed_3_9" name="__tabbed_3" type="radio" /><input id="__tabbed_3_10" name="__tabbed_3" type="radio" /><input id="__tabbed_3_11" name="__tabbed_3" type="radio" /><div class="tabbed-labels"><label for="__tabbed_3_1">Java</label><label for="__tabbed_3_2">C++</label><label for="__tabbed_3_3">Python</label><label for="__tabbed_3_4">Go</label><label for="__tabbed_3_5">JavaScript</label><label for="__tabbed_3_6">TypeScript</label><label for="__tabbed_3_7">C</label><label for="__tabbed_3_8">C#</label><label for="__tabbed_3_9">Swift</label><label for="__tabbed_3_10">Zig</label><label for="__tabbed_3_11">Dart</label></div>
<div class="tabbed-content">
@@ -2943,7 +3024,7 @@ dp[i, c] = \max(dp[i-1, c], dp[i-1, c - wgt[i-1]] + val[i-1])
<nav class="md-footer__inner md-grid" aria-label="页脚" >
<a href="../dp_solution_pipeline/" class="md-footer__link md-footer__link--prev" aria-label="上一页: 13.3. &amp;nbsp; DP 解题思路New" rel="prev">
<a href="../dp_solution_pipeline/" class="md-footer__link md-footer__link--prev" aria-label="上一页: 14.3. &amp;nbsp; DP 解题思路New" rel="prev">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</div>
@@ -2952,20 +3033,20 @@ dp[i, c] = \max(dp[i-1, c], dp[i-1, c - wgt[i-1]] + val[i-1])
上一页
</span>
<div class="md-ellipsis">
13.3. &nbsp; DP 解题思路New
14.3. &nbsp; DP 解题思路New
</div>
</div>
</a>
<a href="../unbounded_knapsack_problem/" class="md-footer__link md-footer__link--next" aria-label="下一页: 13.5. &amp;nbsp; 完全背包问题New" rel="next">
<a href="../unbounded_knapsack_problem/" class="md-footer__link md-footer__link--next" aria-label="下一页: 14.5. &amp;nbsp; 完全背包问题New" rel="next">
<div class="md-footer__title">
<span class="md-footer__direction">
下一页
</span>
<div class="md-ellipsis">
13.5. &nbsp; 完全背包问题New
14.5. &nbsp; 完全背包问题New
</div>
</div>
<div class="md-footer__button md-icon">

View File

@@ -25,7 +25,7 @@
<title>13.7.   小结New - Hello 算法</title>
<title>14.7.   小结New - Hello 算法</title>
@@ -79,7 +79,7 @@
<div data-md-component="skip">
<a href="#137" class="md-skip">
<a href="#147" class="md-skip">
跳转至
</a>
@@ -113,7 +113,7 @@
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
13.7. &nbsp; 小结New
14.7. &nbsp; 小结New
</span>
</div>
@@ -1771,6 +1771,87 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../../chapter_divide_and_conquer/">12. &nbsp; &nbsp; 分治</a>
<label for="__nav_13">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_13">
<span class="md-nav__icon md-icon"></span>
12. &nbsp; &nbsp; 分治
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_divide_and_conquer/divide_and_conquer/" class="md-nav__link">
12.1. &nbsp; 分治算法New
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_divide_and_conquer/build_binary_tree/" class="md-nav__link">
12.2. &nbsp; 构建树问题New
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_14" >
@@ -1782,18 +1863,18 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../../chapter_backtracking/">12. &nbsp; &nbsp; 回溯</a>
<a href="../../chapter_backtracking/">13. &nbsp; &nbsp; 回溯</a>
<label for="__nav_13">
<label for="__nav_14">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_13">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_14_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_14">
<span class="md-nav__icon md-icon"></span>
12. &nbsp; &nbsp; 回溯
13. &nbsp; &nbsp; 回溯
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -1806,7 +1887,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/backtracking_algorithm/" class="md-nav__link">
12.1. &nbsp; 回溯算法
13.1. &nbsp; 回溯算法
</a>
</li>
@@ -1820,7 +1901,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/permutations_problem/" class="md-nav__link">
12.2. &nbsp; 全排列问题
13.2. &nbsp; 全排列问题
</a>
</li>
@@ -1834,7 +1915,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/subset_sum_problem/" class="md-nav__link">
12.3. &nbsp; 子集和问题
13.3. &nbsp; 子集和问题
</a>
</li>
@@ -1848,7 +1929,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/n_queens_problem/" class="md-nav__link">
12.4. &nbsp; N 皇后问题
13.4. &nbsp; N 皇后问题
</a>
</li>
@@ -1862,7 +1943,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/summary/" class="md-nav__link">
12.5. &nbsp; 小结
13.5. &nbsp; 小结
</a>
</li>
@@ -1890,7 +1971,7 @@
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_14" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_15" checked>
@@ -1917,18 +1998,18 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../">13. &nbsp; &nbsp; 动态规划</a>
<a href="../">14. &nbsp; &nbsp; 动态规划</a>
<label for="__nav_14">
<label for="__nav_15">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_14_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_14">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_15_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_15">
<span class="md-nav__icon md-icon"></span>
13. &nbsp; &nbsp; 动态规划
14. &nbsp; &nbsp; 动态规划
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -1941,7 +2022,7 @@
<li class="md-nav__item">
<a href="../intro_to_dynamic_programming/" class="md-nav__link">
13.1. &nbsp; 初探动态规划New
14.1. &nbsp; 初探动态规划New
</a>
</li>
@@ -1955,7 +2036,7 @@
<li class="md-nav__item">
<a href="../dp_problem_features/" class="md-nav__link">
13.2. &nbsp; DP 问题特性New
14.2. &nbsp; DP 问题特性New
</a>
</li>
@@ -1969,7 +2050,7 @@
<li class="md-nav__item">
<a href="../dp_solution_pipeline/" class="md-nav__link">
13.3. &nbsp; DP 解题思路New
14.3. &nbsp; DP 解题思路New
</a>
</li>
@@ -1983,7 +2064,7 @@
<li class="md-nav__item">
<a href="../knapsack_problem/" class="md-nav__link">
13.4. &nbsp; 0-1 背包问题New
14.4. &nbsp; 0-1 背包问题New
</a>
</li>
@@ -1997,7 +2078,7 @@
<li class="md-nav__item">
<a href="../unbounded_knapsack_problem/" class="md-nav__link">
13.5. &nbsp; 完全背包问题New
14.5. &nbsp; 完全背包问题New
</a>
</li>
@@ -2011,7 +2092,7 @@
<li class="md-nav__item">
<a href="../edit_distance_problem/" class="md-nav__link">
13.6. &nbsp; 编辑距离问题New
14.6. &nbsp; 编辑距离问题New
</a>
</li>
@@ -2034,7 +2115,7 @@
<a href="./" class="md-nav__link md-nav__link--active">
13.7. &nbsp; 小结New
14.7. &nbsp; 小结New
</a>
</li>
@@ -2056,75 +2137,6 @@
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_15" >
<label class="md-nav__link" for="__nav_15" id="__nav_15_label" tabindex="0">
14. &nbsp; &nbsp; 附录
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_15_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_15">
<span class="md-nav__icon md-icon"></span>
14. &nbsp; &nbsp; 附录
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_appendix/installation/" class="md-nav__link">
14.1. &nbsp; 编程环境安装
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_appendix/contribution/" class="md-nav__link">
14.2. &nbsp; 一起参与创作
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
@@ -2135,6 +2147,75 @@
<label class="md-nav__link" for="__nav_16" id="__nav_16_label" tabindex="0">
15. &nbsp; &nbsp; 附录
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_16_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_16">
<span class="md-nav__icon md-icon"></span>
15. &nbsp; &nbsp; 附录
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_appendix/installation/" class="md-nav__link">
15.1. &nbsp; 编程环境安装
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_appendix/contribution/" class="md-nav__link">
15.2. &nbsp; 一起参与创作
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_17" >
@@ -2147,8 +2228,8 @@
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_16_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_16">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_17_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_17">
<span class="md-nav__icon md-icon"></span>
参考文献
</label>
@@ -2203,7 +2284,7 @@
<h1 id="137">13.7. &nbsp; 小结<a class="headerlink" href="#137" title="Permanent link">&para;</a></h1>
<h1 id="147">14.7. &nbsp; 小结<a class="headerlink" href="#147" title="Permanent link">&para;</a></h1>
<ul>
<li>动态规划通过将原问题分解为子问题来求解问题,并通过存储子问题的解来规避重复计算,实现高效的计算效率。子问题分解是一种通用的算法思路,在分治、动态规划、回溯中具有不同的性质。</li>
<li>不考虑时间的前提下,所有动态规划问题都可以用回溯(暴力搜索)进行求解,但递归树中存在大量的重叠子问题,效率极低。通过引入记忆化列表,可以存储所有计算过的子问题的解,从而保证重叠子问题只被计算一次。</li>
@@ -2295,7 +2376,7 @@
<nav class="md-footer__inner md-grid" aria-label="页脚" >
<a href="../edit_distance_problem/" class="md-footer__link md-footer__link--prev" aria-label="上一页: 13.6. &amp;nbsp; 编辑距离问题New" rel="prev">
<a href="../edit_distance_problem/" class="md-footer__link md-footer__link--prev" aria-label="上一页: 14.6. &amp;nbsp; 编辑距离问题New" rel="prev">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</div>
@@ -2304,20 +2385,20 @@
上一页
</span>
<div class="md-ellipsis">
13.6. &nbsp; 编辑距离问题New
14.6. &nbsp; 编辑距离问题New
</div>
</div>
</a>
<a href="../../chapter_appendix/installation/" class="md-footer__link md-footer__link--next" aria-label="下一页: 14.1. &amp;nbsp; 编程环境安装" rel="next">
<a href="../../chapter_appendix/installation/" class="md-footer__link md-footer__link--next" aria-label="下一页: 15.1. &amp;nbsp; 编程环境安装" rel="next">
<div class="md-footer__title">
<span class="md-footer__direction">
下一页
</span>
<div class="md-ellipsis">
14.1. &nbsp; 编程环境安装
15.1. &nbsp; 编程环境安装
</div>
</div>
<div class="md-footer__button md-icon">

View File

@@ -25,7 +25,7 @@
<title>13.5.   完全背包问题New - Hello 算法</title>
<title>14.5.   完全背包问题New - Hello 算法</title>
@@ -79,7 +79,7 @@
<div data-md-component="skip">
<a href="#135" class="md-skip">
<a href="#145" class="md-skip">
跳转至
</a>
@@ -113,7 +113,7 @@
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
13.5. &nbsp; 完全背包问题New
14.5. &nbsp; 完全背包问题New
</span>
</div>
@@ -1771,6 +1771,87 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../../chapter_divide_and_conquer/">12. &nbsp; &nbsp; 分治</a>
<label for="__nav_13">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_13">
<span class="md-nav__icon md-icon"></span>
12. &nbsp; &nbsp; 分治
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_divide_and_conquer/divide_and_conquer/" class="md-nav__link">
12.1. &nbsp; 分治算法New
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_divide_and_conquer/build_binary_tree/" class="md-nav__link">
12.2. &nbsp; 构建树问题New
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_14" >
@@ -1782,18 +1863,18 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../../chapter_backtracking/">12. &nbsp; &nbsp; 回溯</a>
<a href="../../chapter_backtracking/">13. &nbsp; &nbsp; 回溯</a>
<label for="__nav_13">
<label for="__nav_14">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_13">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_14_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_14">
<span class="md-nav__icon md-icon"></span>
12. &nbsp; &nbsp; 回溯
13. &nbsp; &nbsp; 回溯
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -1806,7 +1887,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/backtracking_algorithm/" class="md-nav__link">
12.1. &nbsp; 回溯算法
13.1. &nbsp; 回溯算法
</a>
</li>
@@ -1820,7 +1901,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/permutations_problem/" class="md-nav__link">
12.2. &nbsp; 全排列问题
13.2. &nbsp; 全排列问题
</a>
</li>
@@ -1834,7 +1915,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/subset_sum_problem/" class="md-nav__link">
12.3. &nbsp; 子集和问题
13.3. &nbsp; 子集和问题
</a>
</li>
@@ -1848,7 +1929,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/n_queens_problem/" class="md-nav__link">
12.4. &nbsp; N 皇后问题
13.4. &nbsp; N 皇后问题
</a>
</li>
@@ -1862,7 +1943,7 @@
<li class="md-nav__item">
<a href="../../chapter_backtracking/summary/" class="md-nav__link">
12.5. &nbsp; 小结
13.5. &nbsp; 小结
</a>
</li>
@@ -1890,7 +1971,7 @@
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_14" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_15" checked>
@@ -1917,18 +1998,18 @@
<div class="md-nav__link md-nav__link--index ">
<a href="../">13. &nbsp; &nbsp; 动态规划</a>
<a href="../">14. &nbsp; &nbsp; 动态规划</a>
<label for="__nav_14">
<label for="__nav_15">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_14_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_14">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_15_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_15">
<span class="md-nav__icon md-icon"></span>
13. &nbsp; &nbsp; 动态规划
14. &nbsp; &nbsp; 动态规划
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -1941,7 +2022,7 @@
<li class="md-nav__item">
<a href="../intro_to_dynamic_programming/" class="md-nav__link">
13.1. &nbsp; 初探动态规划New
14.1. &nbsp; 初探动态规划New
</a>
</li>
@@ -1955,7 +2036,7 @@
<li class="md-nav__item">
<a href="../dp_problem_features/" class="md-nav__link">
13.2. &nbsp; DP 问题特性New
14.2. &nbsp; DP 问题特性New
</a>
</li>
@@ -1969,7 +2050,7 @@
<li class="md-nav__item">
<a href="../dp_solution_pipeline/" class="md-nav__link">
13.3. &nbsp; DP 解题思路New
14.3. &nbsp; DP 解题思路New
</a>
</li>
@@ -1983,7 +2064,7 @@
<li class="md-nav__item">
<a href="../knapsack_problem/" class="md-nav__link">
13.4. &nbsp; 0-1 背包问题New
14.4. &nbsp; 0-1 背包问题New
</a>
</li>
@@ -2006,12 +2087,12 @@
<label class="md-nav__link md-nav__link--active" for="__toc">
13.5. &nbsp; 完全背包问题New
14.5. &nbsp; 完全背包问题New
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
13.5. &nbsp; 完全背包问题New
14.5. &nbsp; 完全背包问题New
</a>
@@ -2030,22 +2111,22 @@
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#1351" class="md-nav__link">
13.5.1. &nbsp; 完全背包问题
<a href="#1451" class="md-nav__link">
14.5.1. &nbsp; 完全背包问题
</a>
</li>
<li class="md-nav__item">
<a href="#1352" class="md-nav__link">
13.5.2. &nbsp; 零钱兑换问题
<a href="#1452" class="md-nav__link">
14.5.2. &nbsp; 零钱兑换问题
</a>
</li>
<li class="md-nav__item">
<a href="#1353-ii" class="md-nav__link">
13.5.3. &nbsp; 零钱兑换问题 II
<a href="#1453-ii" class="md-nav__link">
14.5.3. &nbsp; 零钱兑换问题 II
</a>
</li>
@@ -2066,7 +2147,7 @@
<li class="md-nav__item">
<a href="../edit_distance_problem/" class="md-nav__link">
13.6. &nbsp; 编辑距离问题New
14.6. &nbsp; 编辑距离问题New
</a>
</li>
@@ -2080,76 +2161,7 @@
<li class="md-nav__item">
<a href="../summary/" class="md-nav__link">
13.7. &nbsp; 小结New
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_15" >
<label class="md-nav__link" for="__nav_15" id="__nav_15_label" tabindex="0">
14. &nbsp; &nbsp; 附录
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_15_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_15">
<span class="md-nav__icon md-icon"></span>
14. &nbsp; &nbsp; 附录
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_appendix/installation/" class="md-nav__link">
14.1. &nbsp; 编程环境安装
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_appendix/contribution/" class="md-nav__link">
14.2. &nbsp; 一起参与创作
14.7. &nbsp; 小结New
</a>
</li>
@@ -2180,6 +2192,75 @@
<label class="md-nav__link" for="__nav_16" id="__nav_16_label" tabindex="0">
15. &nbsp; &nbsp; 附录
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_16_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_16">
<span class="md-nav__icon md-icon"></span>
15. &nbsp; &nbsp; 附录
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter_appendix/installation/" class="md-nav__link">
15.1. &nbsp; 编程环境安装
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter_appendix/contribution/" class="md-nav__link">
15.2. &nbsp; 一起参与创作
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_17" >
@@ -2192,8 +2273,8 @@
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_16_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_16">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_17_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_17">
<span class="md-nav__icon md-icon"></span>
参考文献
</label>
@@ -2234,22 +2315,22 @@
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#1351" class="md-nav__link">
13.5.1. &nbsp; 完全背包问题
<a href="#1451" class="md-nav__link">
14.5.1. &nbsp; 完全背包问题
</a>
</li>
<li class="md-nav__item">
<a href="#1352" class="md-nav__link">
13.5.2. &nbsp; 零钱兑换问题
<a href="#1452" class="md-nav__link">
14.5.2. &nbsp; 零钱兑换问题
</a>
</li>
<li class="md-nav__item">
<a href="#1353-ii" class="md-nav__link">
13.5.3. &nbsp; 零钱兑换问题 II
<a href="#1453-ii" class="md-nav__link">
14.5.3. &nbsp; 零钱兑换问题 II
</a>
</li>
@@ -2277,9 +2358,9 @@
<h1 id="135">13.5. &nbsp; 完全背包问题<a class="headerlink" href="#135" title="Permanent link">&para;</a></h1>
<h1 id="145">14.5. &nbsp; 完全背包问题<a class="headerlink" href="#145" title="Permanent link">&para;</a></h1>
<p>在本节,我们先求解 0-1 背包的一个变种问题:完全背包问题;再了解完全背包的一种特例问题:零钱兑换。</p>
<h2 id="1351">13.5.1. &nbsp; 完全背包问题<a class="headerlink" href="#1351" title="Permanent link">&para;</a></h2>
<h2 id="1451">14.5.1. &nbsp; 完全背包问题<a class="headerlink" href="#1451" title="Permanent link">&para;</a></h2>
<div class="admonition question">
<p class="admonition-title">Question</p>
<p>给定 <span class="arithmatex">\(n\)</span> 种物品,第 <span class="arithmatex">\(i\)</span> 个物品的重量为 <span class="arithmatex">\(wgt[i-1]\)</span> 、价值为 <span class="arithmatex">\(val[i-1]\)</span> ,现在有个容量为 <span class="arithmatex">\(cap\)</span> 的背包,<strong>每种物品可以重复选取</strong>,问在不超过背包容量下背包中物品的最大价值。</p>
@@ -2559,7 +2640,7 @@ dp[i, c] = \max(dp[i-1, c], dp[i, c - wgt[i-1]] + val[i-1])
</div>
</div>
</div>
<h2 id="1352">13.5.2. &nbsp; 零钱兑换问题<a class="headerlink" href="#1352" title="Permanent link">&para;</a></h2>
<h2 id="1452">14.5.2. &nbsp; 零钱兑换问题<a class="headerlink" href="#1452" title="Permanent link">&para;</a></h2>
<p>背包问题是一大类动态规划问题的代表,其拥有很多的变种,例如零钱兑换问题。</p>
<div class="admonition question">
<p class="admonition-title">Question</p>
@@ -2905,7 +2986,7 @@ dp[i, a] = \min(dp[i-1, a], dp[i, a - coins[i-1]] + 1)
</div>
</div>
</div>
<h2 id="1353-ii">13.5.3. &nbsp; 零钱兑换问题 II<a class="headerlink" href="#1353-ii" title="Permanent link">&para;</a></h2>
<h2 id="1453-ii">14.5.3. &nbsp; 零钱兑换问题 II<a class="headerlink" href="#1453-ii" title="Permanent link">&para;</a></h2>
<div class="admonition question">
<p class="admonition-title">Question</p>
<p>给定 <span class="arithmatex">\(n\)</span> 种硬币,第 <span class="arithmatex">\(i\)</span> 个硬币的面值为 <span class="arithmatex">\(coins[i - 1]\)</span> ,目标金额为 <span class="arithmatex">\(amt\)</span> ,每种硬币可以重复选取,<strong>问在凑出目标金额的硬币组合数量</strong></p>
@@ -3249,7 +3330,7 @@ dp[i, a] = dp[i-1, a] + dp[i, a - coins[i-1]]
<nav class="md-footer__inner md-grid" aria-label="页脚" >
<a href="../knapsack_problem/" class="md-footer__link md-footer__link--prev" aria-label="上一页: 13.4. &amp;nbsp; 0-1 背包问题New" rel="prev">
<a href="../knapsack_problem/" class="md-footer__link md-footer__link--prev" aria-label="上一页: 14.4. &amp;nbsp; 0-1 背包问题New" rel="prev">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</div>
@@ -3258,20 +3339,20 @@ dp[i, a] = dp[i-1, a] + dp[i, a - coins[i-1]]
上一页
</span>
<div class="md-ellipsis">
13.4. &nbsp; 0-1 背包问题New
14.4. &nbsp; 0-1 背包问题New
</div>
</div>
</a>
<a href="../edit_distance_problem/" class="md-footer__link md-footer__link--next" aria-label="下一页: 13.6. &amp;nbsp; 编辑距离问题New" rel="next">
<a href="../edit_distance_problem/" class="md-footer__link md-footer__link--next" aria-label="下一页: 14.6. &amp;nbsp; 编辑距离问题New" rel="next">
<div class="md-footer__title">
<span class="md-footer__direction">
下一页
</span>
<div class="md-ellipsis">
13.6. &nbsp; 编辑距离问题New
14.6. &nbsp; 编辑距离问题New
</div>
</div>
<div class="md-footer__button md-icon">