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.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">