deploy
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
@@ -1906,6 +1906,8 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2032,6 +2034,20 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../unbounded_knapsack_problem/" class="md-nav__link">
|
||||
13.5. 完全背包问题(New)
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
@@ -2225,7 +2241,7 @@
|
||||
<p>给定一个楼梯,你每步可以上 <span class="arithmatex">\(1\)</span> 阶或者 <span class="arithmatex">\(2\)</span> 阶,每一阶楼梯上都贴有一个非负整数,表示你在该台阶所需要付出的代价。给定一个非负整数数组 <span class="arithmatex">\(cost\)</span> ,其中 <span class="arithmatex">\(cost[i]\)</span> 表示在第 <span class="arithmatex">\(i\)</span> 个台阶需要付出的代价,<span class="arithmatex">\(cost[0]\)</span> 为地面起始点。请计算最少需要付出多少代价才能到达顶部?</p>
|
||||
</div>
|
||||
<p>如下图所示,若第 <span class="arithmatex">\(1\)</span> , <span class="arithmatex">\(2\)</span> , <span class="arithmatex">\(3\)</span> 阶的代价分别为 <span class="arithmatex">\(1\)</span> , <span class="arithmatex">\(10\)</span> , <span class="arithmatex">\(1\)</span> ,则从地面爬到第 <span class="arithmatex">\(3\)</span> 阶的最小代价为 <span class="arithmatex">\(2\)</span> 。</p>
|
||||
<p><img alt="爬到第 3 阶的最小代价" src="../intro_to_dynamic_programming.assets/min_cost_cs_example.png" /></p>
|
||||
<p><img alt="爬到第 3 阶的最小代价" src="../dp_problem_features.assets/min_cost_cs_example.png" /></p>
|
||||
<p align="center"> Fig. 爬到第 3 阶的最小代价 </p>
|
||||
|
||||
<p>设 <span class="arithmatex">\(dp[i]\)</span> 为爬到第 <span class="arithmatex">\(i\)</span> 阶累计付出的代价,由于第 <span class="arithmatex">\(i\)</span> 阶只可能从 <span class="arithmatex">\(i - 1\)</span> 阶或 <span class="arithmatex">\(i - 2\)</span> 阶走来,因此 <span class="arithmatex">\(dp[i]\)</span> 只可能等于 <span class="arithmatex">\(dp[i - 1] + cost[i]\)</span> 或 <span class="arithmatex">\(dp[i - 2] + cost[i]\)</span> 。为了尽可能减少代价,我们应该选择两者中较小的那一个,即:</p>
|
||||
@@ -2341,7 +2357,7 @@ dp[i] = \min(dp[i-1], dp[i-2]) + cost[i]
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p><img alt="爬楼梯最小代价的动态规划过程" src="../intro_to_dynamic_programming.assets/min_cost_cs_dp.png" /></p>
|
||||
<p><img alt="爬楼梯最小代价的动态规划过程" src="../dp_problem_features.assets/min_cost_cs_dp.png" /></p>
|
||||
<p align="center"> Fig. 爬楼梯最小代价的动态规划过程 </p>
|
||||
|
||||
<p>这道题同样也可以进行状态压缩,将一维压缩至零维,使得空间复杂度从 <span class="arithmatex">\(O(n)\)</span> 降低至 <span class="arithmatex">\(O(1)\)</span> 。</p>
|
||||
@@ -2446,7 +2462,7 @@ dp[i] = \min(dp[i-1], dp[i-2]) + cost[i]
|
||||
<p>给定一个共有 <span class="arithmatex">\(n\)</span> 阶的楼梯,你每步可以上 <span class="arithmatex">\(1\)</span> 阶或者 <span class="arithmatex">\(2\)</span> 阶,<strong>但不能连续两轮跳 <span class="arithmatex">\(1\)</span> 阶</strong>,请问有多少种方案可以爬到楼顶。</p>
|
||||
</div>
|
||||
<p>例如,爬上第 <span class="arithmatex">\(3\)</span> 阶仅剩 <span class="arithmatex">\(2\)</span> 种可行方案,其中连续三次跳 <span class="arithmatex">\(1\)</span> 阶的方案不满足约束条件,因此被舍弃。</p>
|
||||
<p><img alt="带约束爬到第 3 阶的方案数量" src="../intro_to_dynamic_programming.assets/climbing_stairs_constraint_example.png" /></p>
|
||||
<p><img alt="带约束爬到第 3 阶的方案数量" src="../dp_problem_features.assets/climbing_stairs_constraint_example.png" /></p>
|
||||
<p align="center"> Fig. 带约束爬到第 3 阶的方案数量 </p>
|
||||
|
||||
<p>在该问题中,<strong>下一步选择不能由当前状态(当前楼梯阶数)独立决定,还和前一个状态(上轮楼梯阶数)有关</strong>。如果上一轮是跳 <span class="arithmatex">\(1\)</span> 阶上来的,那么下一轮就必须跳 <span class="arithmatex">\(2\)</span> 阶。</p>
|
||||
@@ -2463,7 +2479,7 @@ dp[i, 1] = dp[i-1, 2] \\
|
||||
dp[i, 2] = dp[i-2, 1] + dp[i-2, 2]
|
||||
\end{cases}
|
||||
\]</div>
|
||||
<p><img alt="考虑约束下的递推关系" src="../intro_to_dynamic_programming.assets/climbing_stairs_constraint_state_transfer.png" /></p>
|
||||
<p><img alt="考虑约束下的递推关系" src="../dp_problem_features.assets/climbing_stairs_constraint_state_transfer.png" /></p>
|
||||
<p align="center"> Fig. 考虑约束下的递推关系 </p>
|
||||
|
||||
<p>最终,返回 <span class="arithmatex">\(dp[n, 1] + dp[n, 2]\)</span> 即可,两者之和代表爬到第 <span class="arithmatex">\(n\)</span> 阶的方案总数。</p>
|
||||
|
||||
@@ -1906,6 +1906,8 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2053,6 +2055,20 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../unbounded_knapsack_problem/" class="md-nav__link">
|
||||
13.5. 完全背包问题(New)
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
@@ -2325,12 +2341,12 @@ dp[i, j] = \min(dp[i-1, j], dp[i, j-1]) + grid[i, j]
|
||||
<p class="admonition-title">Note</p>
|
||||
<p>边界条件即初始状态,在搜索中用于剪枝,在动态规划中用于初始化 <span class="arithmatex">\(dp\)</span> 表。状态转移顺序的核心是要保证在计算当前问题时,所有它依赖的更小子问题都已经被正确地计算出来。</p>
|
||||
</div>
|
||||
<p>最后,我们基于以上结果实现解法即可。熟练度较高同学可以直接写出动态规划解法,初学者可以按照“暴力搜索 <span class="arithmatex">\(\rightarrow\)</span> 记忆化搜索 <span class="arithmatex">\(\rightarrow\)</span> 动态规划” 的顺序实现。</p>
|
||||
<p>接下来,我们就可以实现动态规划代码了。然而,由于子问题分解是一种从顶至底的思想,因此按照“暴力搜索 <span class="arithmatex">\(\rightarrow\)</span> 记忆化搜索 <span class="arithmatex">\(\rightarrow\)</span> 动态规划”的顺序实现更加符合思维习惯。</p>
|
||||
<h2 id="1333">13.3.3. 方法一:暴力搜索<a class="headerlink" href="#1333" title="Permanent link">¶</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>
|
||||
<li><strong>终止条件</strong>:当 <span class="arithmatex">\(i = 0\)</span> 且 <span class="arithmatex">\(j = 0\)</span> 时,返回代价 <span class="arithmatex">\(grid[0][0]\)</span> ;</li>
|
||||
<li><strong>终止条件</strong>:当 <span class="arithmatex">\(i = 0\)</span> 且 <span class="arithmatex">\(j = 0\)</span> 时,返回代价 <span class="arithmatex">\(grid[0, 0]\)</span> ;</li>
|
||||
<li><strong>剪枝</strong>:当 <span class="arithmatex">\(i < 0\)</span> 时或 <span class="arithmatex">\(j < 0\)</span> 时索引越界,此时返回代价 <span class="arithmatex">\(+\infty\)</span> ,代表不可行;</li>
|
||||
</ul>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:11"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><input id="__tabbed_1_3" name="__tabbed_1" type="radio" /><input id="__tabbed_1_4" name="__tabbed_1" type="radio" /><input id="__tabbed_1_5" name="__tabbed_1" type="radio" /><input id="__tabbed_1_6" name="__tabbed_1" type="radio" /><input id="__tabbed_1_7" name="__tabbed_1" type="radio" /><input id="__tabbed_1_8" name="__tabbed_1" type="radio" /><input id="__tabbed_1_9" name="__tabbed_1" type="radio" /><input id="__tabbed_1_10" name="__tabbed_1" type="radio" /><input id="__tabbed_1_11" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">Java</label><label for="__tabbed_1_2">C++</label><label for="__tabbed_1_3">Python</label><label for="__tabbed_1_4">Go</label><label for="__tabbed_1_5">JavaScript</label><label for="__tabbed_1_6">TypeScript</label><label for="__tabbed_1_7">C</label><label for="__tabbed_1_8">C#</label><label for="__tabbed_1_9">Swift</label><label for="__tabbed_1_10">Zig</label><label for="__tabbed_1_11">Dart</label></div>
|
||||
|
||||
@@ -1906,6 +1906,8 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1984,6 +1986,20 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="unbounded_knapsack_problem/" class="md-nav__link">
|
||||
13.5. 完全背包问题(New)
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
|
||||
@@ -1906,6 +1906,8 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2039,6 +2041,20 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../unbounded_knapsack_problem/" class="md-nav__link">
|
||||
13.5. 完全背包问题(New)
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<link rel="prev" href="../dp_solution_pipeline/">
|
||||
|
||||
|
||||
<link rel="next" href="../../chapter_appendix/installation/">
|
||||
<link rel="next" href="../unbounded_knapsack_problem/">
|
||||
|
||||
<link rel="icon" href="../../assets/images/favicon.png">
|
||||
<meta name="generator" content="mkdocs-1.4.2, mkdocs-material-9.1.11">
|
||||
@@ -1906,6 +1906,8 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2039,6 +2041,20 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../unbounded_knapsack_problem/" class="md-nav__link">
|
||||
13.5. 完全背包问题(New)
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
@@ -2245,7 +2261,7 @@
|
||||
<p><strong>第一步:思考每轮的决策,定义状态,从而得到 <span class="arithmatex">\(dp\)</span> 表</strong></p>
|
||||
<p>在 0-1 背包问题中,不放入背包,背包容量不变;放入背包,背包容量减小。由此可得状态定义:当前物品编号 <span class="arithmatex">\(i\)</span> 和剩余背包容量 <span class="arithmatex">\(c\)</span> ,记为 <span class="arithmatex">\([i, c]\)</span> 。</p>
|
||||
<p>状态 <span class="arithmatex">\([i, c]\)</span> 对应的子问题为:<strong>前 <span class="arithmatex">\(i\)</span> 个物品在剩余容量为 <span class="arithmatex">\(c\)</span> 的背包中的最大价值</strong>,记为 <span class="arithmatex">\(dp[i, c]\)</span> 。</p>
|
||||
<p>至此,我们得到一个尺寸为 <span class="arithmatex">\(n \times cap\)</span> 的二维 <span class="arithmatex">\(dp\)</span> 矩阵。</p>
|
||||
<p>需要求解的是 <span class="arithmatex">\(dp[n, cap]\)</span> ,因此需要一个尺寸为 <span class="arithmatex">\((n+1) \times (cap+1)\)</span> 的二维 <span class="arithmatex">\(dp\)</span> 表。</p>
|
||||
<p><strong>第二步:找出最优子结构,进而推导出状态转移方程</strong></p>
|
||||
<p>当我们做出物品 <span class="arithmatex">\(i\)</span> 的决策后,剩余的是前 <span class="arithmatex">\(i-1\)</span> 个物品的决策。因此,状态转移分为两种情况:</p>
|
||||
<ul>
|
||||
@@ -2260,6 +2276,10 @@ dp[i, c] = \max(dp[i-1, c], dp[i-1, c - wgt[i-1]] + val[i-1])
|
||||
<p><strong>第三步:确定边界条件和状态转移顺序</strong></p>
|
||||
<p>当无物品或无剩余背包容量时最大价值为 <span class="arithmatex">\(0\)</span> ,即所有 <span class="arithmatex">\(dp[i, 0]\)</span> 和 <span class="arithmatex">\(dp[0, c]\)</span> 都等于 <span class="arithmatex">\(0\)</span> 。</p>
|
||||
<p>当前状态 <span class="arithmatex">\([i, c]\)</span> 从上方的状态 <span class="arithmatex">\([i-1, c]\)</span> 和左上方的状态 <span class="arithmatex">\([i-1, c-wgt[i-1]]\)</span> 转移而来,因此通过两层循环正序遍历整个 <span class="arithmatex">\(dp\)</span> 表即可。</p>
|
||||
<div class="admonition tip">
|
||||
<p class="admonition-title">Tip</p>
|
||||
<p>完成以上三步后,我们可以直接实现从底至顶的动态规划解法。而为了展示本题包含的重叠子问题,本文也同时给出从顶至底的暴力搜索和记忆化搜索解法。</p>
|
||||
</div>
|
||||
<h2 id="1341">13.4.1. 方法一:暴力搜索<a class="headerlink" href="#1341" title="Permanent link">¶</a></h2>
|
||||
<p>搜索代码包含以下要素:</p>
|
||||
<ul>
|
||||
@@ -2510,7 +2530,7 @@ dp[i, c] = \max(dp[i-1, c], dp[i-1, c - wgt[i-1]] + val[i-1])
|
||||
<p align="center"> Fig. 0-1 背包的记忆化搜索递归树 </p>
|
||||
|
||||
<h2 id="1343">13.4.3. 方法三:动态规划<a class="headerlink" href="#1343" title="Permanent link">¶</a></h2>
|
||||
<p>动态规划解法本质上就是在状态转移中填充 <code>dp</code> 矩阵的过程,代码如下所示。</p>
|
||||
<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">
|
||||
<div class="tabbed-block">
|
||||
@@ -2627,7 +2647,7 @@ dp[i, c] = \max(dp[i-1, c], dp[i-1, c - wgt[i-1]] + val[i-1])
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>如下图所示,时间复杂度由 <code>dp</code> 矩阵大小决定,为 <span class="arithmatex">\(O(n \times cap)\)</span> 。</p>
|
||||
<p>如下图所示,时间复杂度由数组 <code>dp</code> 大小决定,为 <span class="arithmatex">\(O(n \times cap)\)</span> 。</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="4:14"><input checked="checked" id="__tabbed_4_1" name="__tabbed_4" type="radio" /><input id="__tabbed_4_2" name="__tabbed_4" type="radio" /><input id="__tabbed_4_3" name="__tabbed_4" type="radio" /><input id="__tabbed_4_4" name="__tabbed_4" type="radio" /><input id="__tabbed_4_5" name="__tabbed_4" type="radio" /><input id="__tabbed_4_6" name="__tabbed_4" type="radio" /><input id="__tabbed_4_7" name="__tabbed_4" type="radio" /><input id="__tabbed_4_8" name="__tabbed_4" type="radio" /><input id="__tabbed_4_9" name="__tabbed_4" type="radio" /><input id="__tabbed_4_10" name="__tabbed_4" type="radio" /><input id="__tabbed_4_11" name="__tabbed_4" type="radio" /><input id="__tabbed_4_12" name="__tabbed_4" type="radio" /><input id="__tabbed_4_13" name="__tabbed_4" type="radio" /><input id="__tabbed_4_14" name="__tabbed_4" type="radio" /><div class="tabbed-labels"><label for="__tabbed_4_1"><1></label><label for="__tabbed_4_2"><2></label><label for="__tabbed_4_3"><3></label><label for="__tabbed_4_4"><4></label><label for="__tabbed_4_5"><5></label><label for="__tabbed_4_6"><6></label><label for="__tabbed_4_7"><7></label><label for="__tabbed_4_8"><8></label><label for="__tabbed_4_9"><9></label><label for="__tabbed_4_10"><10></label><label for="__tabbed_4_11"><11></label><label for="__tabbed_4_12"><12></label><label for="__tabbed_4_13"><13></label><label for="__tabbed_4_14"><14></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
@@ -2674,8 +2694,8 @@ dp[i, c] = \max(dp[i-1, c], dp[i-1, c - wgt[i-1]] + val[i-1])
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p><strong>最后考虑状态压缩</strong>。以上代码中的 <code>dp</code> 矩阵占用 <span class="arithmatex">\(O(n \times cap)\)</span> 空间。由于每个状态都只与其上一行的状态有关,因此我们可以使用两个数组滚动前进,将空间复杂度从 <span class="arithmatex">\(O(n^2)\)</span> 将低至 <span class="arithmatex">\(O(n)\)</span> 。代码省略,有兴趣的同学可以自行实现。</p>
|
||||
<p>那么,我们是否可以仅用一个数组实现状态压缩呢?观察可知,每个状态都是由左上方或正上方的格子转移过来的。假设只有一个数组,当遍历到第 <span class="arithmatex">\(i\)</span> 行时,该数组存储的仍然是第 <span class="arithmatex">\(i-1\)</span> 行的状态,为了避免左边区域的格子在状态转移中被覆盖,我们应采取倒序遍历。</p>
|
||||
<p><strong>最后考虑状态压缩</strong>。以上代码中的数组 <code>dp</code> 占用 <span class="arithmatex">\(O(n \times cap)\)</span> 空间。由于每个状态都只与其上一行的状态有关,因此我们可以使用两个数组滚动前进,将空间复杂度从 <span class="arithmatex">\(O(n^2)\)</span> 将低至 <span class="arithmatex">\(O(n)\)</span> 。代码省略,有兴趣的同学可以自行实现。</p>
|
||||
<p>那么,我们是否可以仅用一个数组实现状态压缩呢?观察可知,每个状态都是由左上方或正上方的格子转移过来的。假设只有一个数组,当遍历到第 <span class="arithmatex">\(i\)</span> 行时,该数组存储的仍然是第 <span class="arithmatex">\(i-1\)</span> 行的状态,<strong>为了避免左方区域的格子在状态转移中被覆盖,应该采取倒序遍历</strong>。</p>
|
||||
<p>以下动画展示了在单个数组下从第 <span class="arithmatex">\(i=1\)</span> 行转换至第 <span class="arithmatex">\(i=2\)</span> 行的过程。建议你思考一下正序遍历和倒序遍历的区别。</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="5:6"><input checked="checked" id="__tabbed_5_1" name="__tabbed_5" type="radio" /><input id="__tabbed_5_2" name="__tabbed_5" type="radio" /><input id="__tabbed_5_3" name="__tabbed_5" type="radio" /><input id="__tabbed_5_4" name="__tabbed_5" type="radio" /><input id="__tabbed_5_5" name="__tabbed_5" type="radio" /><input id="__tabbed_5_6" name="__tabbed_5" type="radio" /><div class="tabbed-labels"><label for="__tabbed_5_1"><1></label><label for="__tabbed_5_2"><2></label><label for="__tabbed_5_3"><3></label><label for="__tabbed_5_4"><4></label><label for="__tabbed_5_5"><5></label><label for="__tabbed_5_6"><6></label></div>
|
||||
<div class="tabbed-content">
|
||||
@@ -2699,7 +2719,7 @@ dp[i, c] = \max(dp[i-1, c], dp[i-1, c - wgt[i-1]] + val[i-1])
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>如以下代码所示,我们仅需将 <code>dp</code> 矩阵的第一维 <span class="arithmatex">\(i\)</span> 直接删除,并且将内循环修改为倒序遍历即可。</p>
|
||||
<p>如以下代码所示,我们仅需将数组 <code>dp</code> 的第一维 <span class="arithmatex">\(i\)</span> 直接删除,并且将内循环修改为倒序遍历即可。</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="6:11"><input checked="checked" id="__tabbed_6_1" name="__tabbed_6" type="radio" /><input id="__tabbed_6_2" name="__tabbed_6" type="radio" /><input id="__tabbed_6_3" name="__tabbed_6" type="radio" /><input id="__tabbed_6_4" name="__tabbed_6" type="radio" /><input id="__tabbed_6_5" name="__tabbed_6" type="radio" /><input id="__tabbed_6_6" name="__tabbed_6" type="radio" /><input id="__tabbed_6_7" name="__tabbed_6" type="radio" /><input id="__tabbed_6_8" name="__tabbed_6" type="radio" /><input id="__tabbed_6_9" name="__tabbed_6" type="radio" /><input id="__tabbed_6_10" name="__tabbed_6" type="radio" /><input id="__tabbed_6_11" name="__tabbed_6" type="radio" /><div class="tabbed-labels"><label for="__tabbed_6_1">Java</label><label for="__tabbed_6_2">C++</label><label for="__tabbed_6_3">Python</label><label for="__tabbed_6_4">Go</label><label for="__tabbed_6_5">JavaScript</label><label for="__tabbed_6_6">TypeScript</label><label for="__tabbed_6_7">C</label><label for="__tabbed_6_8">C#</label><label for="__tabbed_6_9">Swift</label><label for="__tabbed_6_10">Zig</label><label for="__tabbed_6_11">Dart</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
@@ -2907,13 +2927,13 @@ dp[i, c] = \max(dp[i-1, c], dp[i-1, c - wgt[i-1]] + val[i-1])
|
||||
|
||||
|
||||
|
||||
<a href="../../chapter_appendix/installation/" class="md-footer__link md-footer__link--next" aria-label="下一页: 14.1. &nbsp; 编程环境安装" rel="next">
|
||||
<a href="../unbounded_knapsack_problem/" class="md-footer__link md-footer__link--next" aria-label="下一页: 13.5. &nbsp; 完全背包问题(New)" rel="next">
|
||||
<div class="md-footer__title">
|
||||
<span class="md-footer__direction">
|
||||
下一页
|
||||
</span>
|
||||
<div class="md-ellipsis">
|
||||
14.1. 编程环境安装
|
||||
13.5. 完全背包问题(New)
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
|
||||
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 69 KiB |