mirror of
https://github.com/krahets/hello-algo.git
synced 2025-07-24 02:03:10 +08:00
deploy
This commit is contained in:
@ -3433,9 +3433,9 @@
|
||||
<p class="admonition-title">爬楼梯最小代价</p>
|
||||
<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>如图 14-6 所示,若第 <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="../dp_problem_features.assets/min_cost_cs_example.png" /></p>
|
||||
<p align="center"> 图:爬到第 3 阶的最小代价 </p>
|
||||
<p align="center"> 图 14-6 爬到第 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>
|
||||
<div class="arithmatex">\[
|
||||
@ -3630,9 +3630,9 @@ dp[i] = \min(dp[i-1], dp[i-2]) + cost[i]
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>下图展示了以上代码的动态规划过程。</p>
|
||||
<p>图 14-7 展示了以上代码的动态规划过程。</p>
|
||||
<p><img alt="爬楼梯最小代价的动态规划过程" src="../dp_problem_features.assets/min_cost_cs_dp.png" /></p>
|
||||
<p align="center"> 图:爬楼梯最小代价的动态规划过程 </p>
|
||||
<p align="center"> 图 14-7 爬楼梯最小代价的动态规划过程 </p>
|
||||
|
||||
<p>本题也可以进行状态压缩,将一维压缩至零维,使得空间复杂度从 <span class="arithmatex">\(O(n)\)</span> 降低至 <span class="arithmatex">\(O(1)\)</span> 。</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="2:12"><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" /><input id="__tabbed_2_12" 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">JS</label><label for="__tabbed_2_6">TS</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><label for="__tabbed_2_12">Rust</label></div>
|
||||
@ -3802,9 +3802,9 @@ dp[i] = \min(dp[i-1], dp[i-2]) + cost[i]
|
||||
<p class="admonition-title">带约束爬楼梯</p>
|
||||
<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>例如图 14-8 ,爬上第 <span class="arithmatex">\(3\)</span> 阶仅剩 <span class="arithmatex">\(2\)</span> 种可行方案,其中连续三次跳 <span class="arithmatex">\(1\)</span> 阶的方案不满足约束条件,因此被舍弃。</p>
|
||||
<p><img alt="带约束爬到第 3 阶的方案数量" src="../dp_problem_features.assets/climbing_stairs_constraint_example.png" /></p>
|
||||
<p align="center"> 图:带约束爬到第 3 阶的方案数量 </p>
|
||||
<p align="center"> 图 14-8 带约束爬到第 3 阶的方案数量 </p>
|
||||
|
||||
<p>在该问题中,如果上一轮是跳 <span class="arithmatex">\(1\)</span> 阶上来的,那么下一轮就必须跳 <span class="arithmatex">\(2\)</span> 阶。这意味着,<strong>下一步选择不能由当前状态(当前楼梯阶数)独立决定,还和前一个状态(上轮楼梯阶数)有关</strong>。</p>
|
||||
<p>不难发现,此问题已不满足无后效性,状态转移方程 <span class="arithmatex">\(dp[i] = dp[i-1] + dp[i-2]\)</span> 也失效了,因为 <span class="arithmatex">\(dp[i-1]\)</span> 代表本轮跳 <span class="arithmatex">\(1\)</span> 阶,但其中包含了许多“上一轮跳 <span class="arithmatex">\(1\)</span> 阶上来的”方案,而为了满足约束,我们就不能将 <span class="arithmatex">\(dp[i-1]\)</span> 直接计入 <span class="arithmatex">\(dp[i]\)</span> 中。</p>
|
||||
@ -3813,7 +3813,7 @@ dp[i] = \min(dp[i-1], dp[i-2]) + cost[i]
|
||||
<li>当 <span class="arithmatex">\(j\)</span> 等于 <span class="arithmatex">\(1\)</span> ,即上一轮跳了 <span class="arithmatex">\(1\)</span> 阶时,这一轮只能选择跳 <span class="arithmatex">\(2\)</span> 阶。</li>
|
||||
<li>当 <span class="arithmatex">\(j\)</span> 等于 <span class="arithmatex">\(2\)</span> ,即上一轮跳了 <span class="arithmatex">\(2\)</span> 阶时,这一轮可选择跳 <span class="arithmatex">\(1\)</span> 阶或跳 <span class="arithmatex">\(2\)</span> 阶。</li>
|
||||
</ul>
|
||||
<p>如下图所示,在该定义下,<span class="arithmatex">\(dp[i, j]\)</span> 表示状态 <span class="arithmatex">\([i, j]\)</span> 对应的方案数。此时状态转移方程为:</p>
|
||||
<p>如图 14-9 所示,在该定义下,<span class="arithmatex">\(dp[i, j]\)</span> 表示状态 <span class="arithmatex">\([i, j]\)</span> 对应的方案数。此时状态转移方程为:</p>
|
||||
<div class="arithmatex">\[
|
||||
\begin{cases}
|
||||
dp[i, 1] = dp[i-1, 2] \\
|
||||
@ -3821,7 +3821,7 @@ dp[i, 2] = dp[i-2, 1] + dp[i-2, 2]
|
||||
\end{cases}
|
||||
\]</div>
|
||||
<p><img alt="考虑约束下的递推关系" src="../dp_problem_features.assets/climbing_stairs_constraint_state_transfer.png" /></p>
|
||||
<p align="center"> 图:考虑约束下的递推关系 </p>
|
||||
<p align="center"> 图 14-9 考虑约束下的递推关系 </p>
|
||||
|
||||
<p>最终,返回 <span class="arithmatex">\(dp[n, 1] + dp[n, 2]\)</span> 即可,两者之和代表爬到第 <span class="arithmatex">\(n\)</span> 阶的方案总数。</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="3:12"><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" /><input id="__tabbed_3_12" 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">JS</label><label for="__tabbed_3_6">TS</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><label for="__tabbed_3_12">Rust</label></div>
|
||||
|
Reference in New Issue
Block a user