This commit is contained in:
krahets
2023-11-09 05:13:48 +08:00
parent 9701430089
commit 0105644232
83 changed files with 516 additions and 509 deletions

View File

@@ -22,7 +22,7 @@ comments: true
如图 14-6 所示,若第 $1$、$2$、$3$ 阶的代价分别为 $1$、$10$、$1$ ,则从地面爬到第 $3$ 阶的最小代价为 $2$ 。
![爬到第 3 阶的最小代价](dp_problem_features.assets/min_cost_cs_example.png)
![爬到第 3 阶的最小代价](dp_problem_features.assets/min_cost_cs_example.png){ class="animation-figure" }
<p align="center"> 图 14-6 &nbsp; 爬到第 3 阶的最小代价 </p>
@@ -300,7 +300,7 @@ $$
图 14-7 展示了以上代码的动态规划过程。
![爬楼梯最小代价的动态规划过程](dp_problem_features.assets/min_cost_cs_dp.png)
![爬楼梯最小代价的动态规划过程](dp_problem_features.assets/min_cost_cs_dp.png){ class="animation-figure" }
<p align="center"> 图 14-7 &nbsp; 爬楼梯最小代价的动态规划过程 </p>
@@ -545,7 +545,7 @@ $$
例如图 14-8 ,爬上第 $3$ 阶仅剩 $2$ 种可行方案,其中连续三次跳 $1$ 阶的方案不满足约束条件,因此被舍弃。
![带约束爬到第 3 阶的方案数量](dp_problem_features.assets/climbing_stairs_constraint_example.png)
![带约束爬到第 3 阶的方案数量](dp_problem_features.assets/climbing_stairs_constraint_example.png){ class="animation-figure" }
<p align="center"> 图 14-8 &nbsp; 带约束爬到第 3 阶的方案数量 </p>
@@ -567,7 +567,7 @@ dp[i, 2] = dp[i-2, 1] + dp[i-2, 2]
\end{cases}
$$
![考虑约束下的递推关系](dp_problem_features.assets/climbing_stairs_constraint_state_transfer.png)
![考虑约束下的递推关系](dp_problem_features.assets/climbing_stairs_constraint_state_transfer.png){ class="animation-figure" }
<p align="center"> 图 14-9 &nbsp; 考虑约束下的递推关系 </p>

View File

@@ -41,7 +41,7 @@ comments: true
图 14-10 展示了一个例子,给定网格的最小路径和为 $13$ 。
![最小路径和示例数据](dp_solution_pipeline.assets/min_path_sum_example.png)
![最小路径和示例数据](dp_solution_pipeline.assets/min_path_sum_example.png){ class="animation-figure" }
<p align="center"> 图 14-10 &nbsp; 最小路径和示例数据 </p>
@@ -53,7 +53,7 @@ comments: true
至此,我们就得到了图 14-11 所示的二维 $dp$ 矩阵,其尺寸与输入网格 $grid$ 相同。
![状态定义与 dp 表](dp_solution_pipeline.assets/min_path_sum_solution_step1.png)
![状态定义与 dp 表](dp_solution_pipeline.assets/min_path_sum_solution_step1.png){ class="animation-figure" }
<p align="center"> 图 14-11 &nbsp; 状态定义与 dp 表 </p>
@@ -73,7 +73,7 @@ $$
dp[i, j] = \min(dp[i-1, j], dp[i, j-1]) + grid[i, j]
$$
![最优子结构与状态转移方程](dp_solution_pipeline.assets/min_path_sum_solution_step2.png)
![最优子结构与状态转移方程](dp_solution_pipeline.assets/min_path_sum_solution_step2.png){ class="animation-figure" }
<p align="center"> 图 14-12 &nbsp; 最优子结构与状态转移方程 </p>
@@ -89,7 +89,7 @@ $$
如图 14-13 所示,由于每个格子是由其左方格子和上方格子转移而来,因此我们使用采用循环来遍历矩阵,外循环遍历各行、内循环遍历各列。
![边界条件与状态转移顺序](dp_solution_pipeline.assets/min_path_sum_solution_step3.png)
![边界条件与状态转移顺序](dp_solution_pipeline.assets/min_path_sum_solution_step3.png){ class="animation-figure" }
<p align="center"> 图 14-13 &nbsp; 边界条件与状态转移顺序 </p>
@@ -368,7 +368,7 @@ $$
本质上看,造成重叠子问题的原因为:**存在多条路径可以从左上角到达某一单元格**。
![暴力搜索递归树](dp_solution_pipeline.assets/min_path_sum_dfs.png)
![暴力搜索递归树](dp_solution_pipeline.assets/min_path_sum_dfs.png){ class="animation-figure" }
<p align="center"> 图 14-14 &nbsp; 暴力搜索递归树 </p>
@@ -697,7 +697,7 @@ $$
如图 14-15 所示,在引入记忆化后,所有子问题的解只需计算一次,因此时间复杂度取决于状态总数,即网格尺寸 $O(nm)$ 。
![记忆化搜索递归树](dp_solution_pipeline.assets/min_path_sum_dfs_mem.png)
![记忆化搜索递归树](dp_solution_pipeline.assets/min_path_sum_dfs_mem.png){ class="animation-figure" }
<p align="center"> 图 14-15 &nbsp; 记忆化搜索递归树 </p>
@@ -1039,40 +1039,40 @@ $$
数组 `dp` 大小为 $n \times m$ **因此空间复杂度为 $O(nm)$** 。
=== "<1>"
![最小路径和的动态规划过程](dp_solution_pipeline.assets/min_path_sum_dp_step1.png)
![最小路径和的动态规划过程](dp_solution_pipeline.assets/min_path_sum_dp_step1.png){ class="animation-figure" }
=== "<2>"
![min_path_sum_dp_step2](dp_solution_pipeline.assets/min_path_sum_dp_step2.png)
![min_path_sum_dp_step2](dp_solution_pipeline.assets/min_path_sum_dp_step2.png){ class="animation-figure" }
=== "<3>"
![min_path_sum_dp_step3](dp_solution_pipeline.assets/min_path_sum_dp_step3.png)
![min_path_sum_dp_step3](dp_solution_pipeline.assets/min_path_sum_dp_step3.png){ class="animation-figure" }
=== "<4>"
![min_path_sum_dp_step4](dp_solution_pipeline.assets/min_path_sum_dp_step4.png)
![min_path_sum_dp_step4](dp_solution_pipeline.assets/min_path_sum_dp_step4.png){ class="animation-figure" }
=== "<5>"
![min_path_sum_dp_step5](dp_solution_pipeline.assets/min_path_sum_dp_step5.png)
![min_path_sum_dp_step5](dp_solution_pipeline.assets/min_path_sum_dp_step5.png){ class="animation-figure" }
=== "<6>"
![min_path_sum_dp_step6](dp_solution_pipeline.assets/min_path_sum_dp_step6.png)
![min_path_sum_dp_step6](dp_solution_pipeline.assets/min_path_sum_dp_step6.png){ class="animation-figure" }
=== "<7>"
![min_path_sum_dp_step7](dp_solution_pipeline.assets/min_path_sum_dp_step7.png)
![min_path_sum_dp_step7](dp_solution_pipeline.assets/min_path_sum_dp_step7.png){ class="animation-figure" }
=== "<8>"
![min_path_sum_dp_step8](dp_solution_pipeline.assets/min_path_sum_dp_step8.png)
![min_path_sum_dp_step8](dp_solution_pipeline.assets/min_path_sum_dp_step8.png){ class="animation-figure" }
=== "<9>"
![min_path_sum_dp_step9](dp_solution_pipeline.assets/min_path_sum_dp_step9.png)
![min_path_sum_dp_step9](dp_solution_pipeline.assets/min_path_sum_dp_step9.png){ class="animation-figure" }
=== "<10>"
![min_path_sum_dp_step10](dp_solution_pipeline.assets/min_path_sum_dp_step10.png)
![min_path_sum_dp_step10](dp_solution_pipeline.assets/min_path_sum_dp_step10.png){ class="animation-figure" }
=== "<11>"
![min_path_sum_dp_step11](dp_solution_pipeline.assets/min_path_sum_dp_step11.png)
![min_path_sum_dp_step11](dp_solution_pipeline.assets/min_path_sum_dp_step11.png){ class="animation-figure" }
=== "<12>"
![min_path_sum_dp_step12](dp_solution_pipeline.assets/min_path_sum_dp_step12.png)
![min_path_sum_dp_step12](dp_solution_pipeline.assets/min_path_sum_dp_step12.png){ class="animation-figure" }
<p align="center"> 图 14-16 &nbsp; 最小路径和的动态规划过程 </p>

View File

@@ -14,7 +14,7 @@ comments: true
如图 14-27 所示,将 `kitten` 转换为 `sitting` 需要编辑 3 步,包括 2 次替换操作与 1 次添加操作;将 `hello` 转换为 `algo` 需要 3 步,包括 2 次替换操作和 1 次删除操作。
![编辑距离的示例数据](edit_distance_problem.assets/edit_distance_example.png)
![编辑距离的示例数据](edit_distance_problem.assets/edit_distance_example.png){ class="animation-figure" }
<p align="center"> 图 14-27 &nbsp; 编辑距离的示例数据 </p>
@@ -24,7 +24,7 @@ comments: true
从决策树的角度看,本题的目标是求解节点 `hello` 和节点 `algo` 之间的最短路径。
![基于决策树模型表示编辑距离问题](edit_distance_problem.assets/edit_distance_decision_tree.png)
![基于决策树模型表示编辑距离问题](edit_distance_problem.assets/edit_distance_decision_tree.png){ class="animation-figure" }
<p align="center"> 图 14-28 &nbsp; 基于决策树模型表示编辑距离问题 </p>
@@ -53,7 +53,7 @@ comments: true
2. 删除 $s[i-1]$ ,则剩余子问题 $dp[i-1, j]$ 。
3. 将 $s[i-1]$ 替换为 $t[j-1]$ ,则剩余子问题 $dp[i-1, j-1]$ 。
![编辑距离的状态转移](edit_distance_problem.assets/edit_distance_state_transfer.png)
![编辑距离的状态转移](edit_distance_problem.assets/edit_distance_state_transfer.png){ class="animation-figure" }
<p align="center"> 图 14-29 &nbsp; 编辑距离的状态转移 </p>
@@ -446,49 +446,49 @@ $$
如图 14-30 所示,编辑距离问题的状态转移过程与背包问题非常类似,都可以看作是填写一个二维网格的过程。
=== "<1>"
![编辑距离的动态规划过程](edit_distance_problem.assets/edit_distance_dp_step1.png)
![编辑距离的动态规划过程](edit_distance_problem.assets/edit_distance_dp_step1.png){ class="animation-figure" }
=== "<2>"
![edit_distance_dp_step2](edit_distance_problem.assets/edit_distance_dp_step2.png)
![edit_distance_dp_step2](edit_distance_problem.assets/edit_distance_dp_step2.png){ class="animation-figure" }
=== "<3>"
![edit_distance_dp_step3](edit_distance_problem.assets/edit_distance_dp_step3.png)
![edit_distance_dp_step3](edit_distance_problem.assets/edit_distance_dp_step3.png){ class="animation-figure" }
=== "<4>"
![edit_distance_dp_step4](edit_distance_problem.assets/edit_distance_dp_step4.png)
![edit_distance_dp_step4](edit_distance_problem.assets/edit_distance_dp_step4.png){ class="animation-figure" }
=== "<5>"
![edit_distance_dp_step5](edit_distance_problem.assets/edit_distance_dp_step5.png)
![edit_distance_dp_step5](edit_distance_problem.assets/edit_distance_dp_step5.png){ class="animation-figure" }
=== "<6>"
![edit_distance_dp_step6](edit_distance_problem.assets/edit_distance_dp_step6.png)
![edit_distance_dp_step6](edit_distance_problem.assets/edit_distance_dp_step6.png){ class="animation-figure" }
=== "<7>"
![edit_distance_dp_step7](edit_distance_problem.assets/edit_distance_dp_step7.png)
![edit_distance_dp_step7](edit_distance_problem.assets/edit_distance_dp_step7.png){ class="animation-figure" }
=== "<8>"
![edit_distance_dp_step8](edit_distance_problem.assets/edit_distance_dp_step8.png)
![edit_distance_dp_step8](edit_distance_problem.assets/edit_distance_dp_step8.png){ class="animation-figure" }
=== "<9>"
![edit_distance_dp_step9](edit_distance_problem.assets/edit_distance_dp_step9.png)
![edit_distance_dp_step9](edit_distance_problem.assets/edit_distance_dp_step9.png){ class="animation-figure" }
=== "<10>"
![edit_distance_dp_step10](edit_distance_problem.assets/edit_distance_dp_step10.png)
![edit_distance_dp_step10](edit_distance_problem.assets/edit_distance_dp_step10.png){ class="animation-figure" }
=== "<11>"
![edit_distance_dp_step11](edit_distance_problem.assets/edit_distance_dp_step11.png)
![edit_distance_dp_step11](edit_distance_problem.assets/edit_distance_dp_step11.png){ class="animation-figure" }
=== "<12>"
![edit_distance_dp_step12](edit_distance_problem.assets/edit_distance_dp_step12.png)
![edit_distance_dp_step12](edit_distance_problem.assets/edit_distance_dp_step12.png){ class="animation-figure" }
=== "<13>"
![edit_distance_dp_step13](edit_distance_problem.assets/edit_distance_dp_step13.png)
![edit_distance_dp_step13](edit_distance_problem.assets/edit_distance_dp_step13.png){ class="animation-figure" }
=== "<14>"
![edit_distance_dp_step14](edit_distance_problem.assets/edit_distance_dp_step14.png)
![edit_distance_dp_step14](edit_distance_problem.assets/edit_distance_dp_step14.png){ class="animation-figure" }
=== "<15>"
![edit_distance_dp_step15](edit_distance_problem.assets/edit_distance_dp_step15.png)
![edit_distance_dp_step15](edit_distance_problem.assets/edit_distance_dp_step15.png){ class="animation-figure" }
<p align="center"> 图 14-30 &nbsp; 编辑距离的动态规划过程 </p>

View File

@@ -7,7 +7,7 @@ icon: material/table-pivot
<div class="center-table" markdown>
![动态规划](../assets/covers/chapter_dynamic_programming.jpg){ width="600" }
![动态规划](../assets/covers/chapter_dynamic_programming.jpg){ class="cover-image" }
</div>

View File

@@ -14,7 +14,7 @@ comments: true
如图 14-1 所示,对于一个 $3$ 阶楼梯,共有 $3$ 种方案可以爬到楼顶。
![爬到第 3 阶的方案数量](intro_to_dynamic_programming.assets/climbing_stairs_example.png)
![爬到第 3 阶的方案数量](intro_to_dynamic_programming.assets/climbing_stairs_example.png){ class="animation-figure" }
<p align="center"> 图 14-1 &nbsp; 爬到第 3 阶的方案数量 </p>
@@ -405,7 +405,7 @@ $$
这意味着在爬楼梯问题中,各个子问题之间存在递推关系,**原问题的解可以由子问题的解构建得来**。图 14-2 展示了该递推关系。
![方案数量递推关系](intro_to_dynamic_programming.assets/climbing_stairs_state_transfer.png)
![方案数量递推关系](intro_to_dynamic_programming.assets/climbing_stairs_state_transfer.png){ class="animation-figure" }
<p align="center"> 图 14-2 &nbsp; 方案数量递推关系 </p>
@@ -640,7 +640,7 @@ $$
图 14-3 展示了暴力搜索形成的递归树。对于问题 $dp[n]$ ,其递归树的深度为 $n$ ,时间复杂度为 $O(2^n)$ 。指数阶属于爆炸式增长,如果我们输入一个比较大的 $n$ ,则会陷入漫长的等待之中。
![爬楼梯对应递归树](intro_to_dynamic_programming.assets/climbing_stairs_dfs_tree.png)
![爬楼梯对应递归树](intro_to_dynamic_programming.assets/climbing_stairs_dfs_tree.png){ class="animation-figure" }
<p align="center"> 图 14-3 &nbsp; 爬楼梯对应递归树 </p>
@@ -975,7 +975,7 @@ $$
观察图 14-4 **经过记忆化处理后,所有重叠子问题都只需被计算一次,时间复杂度被优化至 $O(n)$** ,这是一个巨大的飞跃。
![记忆化搜索对应递归树](intro_to_dynamic_programming.assets/climbing_stairs_dfs_memo_tree.png)
![记忆化搜索对应递归树](intro_to_dynamic_programming.assets/climbing_stairs_dfs_memo_tree.png){ class="animation-figure" }
<p align="center"> 图 14-4 &nbsp; 记忆化搜索对应递归树 </p>
@@ -1229,7 +1229,7 @@ $$
图 14-5 模拟了以上代码的执行过程。
![爬楼梯的动态规划过程](intro_to_dynamic_programming.assets/climbing_stairs_dp.png)
![爬楼梯的动态规划过程](intro_to_dynamic_programming.assets/climbing_stairs_dp.png){ class="animation-figure" }
<p align="center"> 图 14-5 &nbsp; 爬楼梯的动态规划过程 </p>

View File

@@ -14,7 +14,7 @@ comments: true
观察图 14-17 ,由于物品编号 $i$ 从 $1$ 开始计数,数组索引从 $0$ 开始计数,因此物品 $i$ 对应重量 $wgt[i-1]$ 和价值 $val[i-1]$ 。
![0-1 背包的示例数据](knapsack_problem.assets/knapsack_example.png)
![0-1 背包的示例数据](knapsack_problem.assets/knapsack_example.png){ class="animation-figure" }
<p align="center"> 图 14-17 &nbsp; 0-1 背包的示例数据 </p>
@@ -320,7 +320,7 @@ $$
观察递归树,容易发现其中存在重叠子问题,例如 $dp[1, 10]$ 等。而当物品较多、背包容量较大,尤其是相同重量的物品较多时,重叠子问题的数量将会大幅增多。
![0-1 背包的暴力搜索递归树](knapsack_problem.assets/knapsack_dfs.png)
![0-1 背包的暴力搜索递归树](knapsack_problem.assets/knapsack_dfs.png){ class="animation-figure" }
<p align="center"> 图 14-18 &nbsp; 0-1 背包的暴力搜索递归树 </p>
@@ -656,7 +656,7 @@ $$
图 14-19 展示了在记忆化递归中被剪掉的搜索分支。
![0-1 背包的记忆化搜索递归树](knapsack_problem.assets/knapsack_dfs_mem.png)
![0-1 背包的记忆化搜索递归树](knapsack_problem.assets/knapsack_dfs_mem.png){ class="animation-figure" }
<p align="center"> 图 14-19 &nbsp; 0-1 背包的记忆化搜索递归树 </p>
@@ -969,46 +969,46 @@ $$
如图 14-20 所示,时间复杂度和空间复杂度都由数组 `dp` 大小决定,即 $O(n \times cap)$ 。
=== "<1>"
![0-1 背包的动态规划过程](knapsack_problem.assets/knapsack_dp_step1.png)
![0-1 背包的动态规划过程](knapsack_problem.assets/knapsack_dp_step1.png){ class="animation-figure" }
=== "<2>"
![knapsack_dp_step2](knapsack_problem.assets/knapsack_dp_step2.png)
![knapsack_dp_step2](knapsack_problem.assets/knapsack_dp_step2.png){ class="animation-figure" }
=== "<3>"
![knapsack_dp_step3](knapsack_problem.assets/knapsack_dp_step3.png)
![knapsack_dp_step3](knapsack_problem.assets/knapsack_dp_step3.png){ class="animation-figure" }
=== "<4>"
![knapsack_dp_step4](knapsack_problem.assets/knapsack_dp_step4.png)
![knapsack_dp_step4](knapsack_problem.assets/knapsack_dp_step4.png){ class="animation-figure" }
=== "<5>"
![knapsack_dp_step5](knapsack_problem.assets/knapsack_dp_step5.png)
![knapsack_dp_step5](knapsack_problem.assets/knapsack_dp_step5.png){ class="animation-figure" }
=== "<6>"
![knapsack_dp_step6](knapsack_problem.assets/knapsack_dp_step6.png)
![knapsack_dp_step6](knapsack_problem.assets/knapsack_dp_step6.png){ class="animation-figure" }
=== "<7>"
![knapsack_dp_step7](knapsack_problem.assets/knapsack_dp_step7.png)
![knapsack_dp_step7](knapsack_problem.assets/knapsack_dp_step7.png){ class="animation-figure" }
=== "<8>"
![knapsack_dp_step8](knapsack_problem.assets/knapsack_dp_step8.png)
![knapsack_dp_step8](knapsack_problem.assets/knapsack_dp_step8.png){ class="animation-figure" }
=== "<9>"
![knapsack_dp_step9](knapsack_problem.assets/knapsack_dp_step9.png)
![knapsack_dp_step9](knapsack_problem.assets/knapsack_dp_step9.png){ class="animation-figure" }
=== "<10>"
![knapsack_dp_step10](knapsack_problem.assets/knapsack_dp_step10.png)
![knapsack_dp_step10](knapsack_problem.assets/knapsack_dp_step10.png){ class="animation-figure" }
=== "<11>"
![knapsack_dp_step11](knapsack_problem.assets/knapsack_dp_step11.png)
![knapsack_dp_step11](knapsack_problem.assets/knapsack_dp_step11.png){ class="animation-figure" }
=== "<12>"
![knapsack_dp_step12](knapsack_problem.assets/knapsack_dp_step12.png)
![knapsack_dp_step12](knapsack_problem.assets/knapsack_dp_step12.png){ class="animation-figure" }
=== "<13>"
![knapsack_dp_step13](knapsack_problem.assets/knapsack_dp_step13.png)
![knapsack_dp_step13](knapsack_problem.assets/knapsack_dp_step13.png){ class="animation-figure" }
=== "<14>"
![knapsack_dp_step14](knapsack_problem.assets/knapsack_dp_step14.png)
![knapsack_dp_step14](knapsack_problem.assets/knapsack_dp_step14.png){ class="animation-figure" }
<p align="center"> 图 14-20 &nbsp; 0-1 背包的动态规划过程 </p>
@@ -1024,22 +1024,22 @@ $$
图 14-21 展示了在单个数组下从第 $i = 1$ 行转换至第 $i = 2$ 行的过程。请思考正序遍历和倒序遍历的区别。
=== "<1>"
![0-1 背包的空间优化后的动态规划过程](knapsack_problem.assets/knapsack_dp_comp_step1.png)
![0-1 背包的空间优化后的动态规划过程](knapsack_problem.assets/knapsack_dp_comp_step1.png){ class="animation-figure" }
=== "<2>"
![knapsack_dp_comp_step2](knapsack_problem.assets/knapsack_dp_comp_step2.png)
![knapsack_dp_comp_step2](knapsack_problem.assets/knapsack_dp_comp_step2.png){ class="animation-figure" }
=== "<3>"
![knapsack_dp_comp_step3](knapsack_problem.assets/knapsack_dp_comp_step3.png)
![knapsack_dp_comp_step3](knapsack_problem.assets/knapsack_dp_comp_step3.png){ class="animation-figure" }
=== "<4>"
![knapsack_dp_comp_step4](knapsack_problem.assets/knapsack_dp_comp_step4.png)
![knapsack_dp_comp_step4](knapsack_problem.assets/knapsack_dp_comp_step4.png){ class="animation-figure" }
=== "<5>"
![knapsack_dp_comp_step5](knapsack_problem.assets/knapsack_dp_comp_step5.png)
![knapsack_dp_comp_step5](knapsack_problem.assets/knapsack_dp_comp_step5.png){ class="animation-figure" }
=== "<6>"
![knapsack_dp_comp_step6](knapsack_problem.assets/knapsack_dp_comp_step6.png)
![knapsack_dp_comp_step6](knapsack_problem.assets/knapsack_dp_comp_step6.png){ class="animation-figure" }
<p align="center"> 图 14-21 &nbsp; 0-1 背包的空间优化后的动态规划过程 </p>

View File

@@ -12,7 +12,7 @@ comments: true
给定 $n$ 个物品,第 $i$ 个物品的重量为 $wgt[i-1]$、价值为 $val[i-1]$ ,和一个容量为 $cap$ 的背包。**每个物品可以重复选取**,问在不超过背包容量下能放入物品的最大价值。
![完全背包问题的示例数据](unbounded_knapsack_problem.assets/unbounded_knapsack_example.png)
![完全背包问题的示例数据](unbounded_knapsack_problem.assets/unbounded_knapsack_example.png){ class="animation-figure" }
<p align="center"> 图 14-22 &nbsp; 完全背包问题的示例数据 </p>
@@ -347,22 +347,22 @@ $$
这个遍历顺序与 0-1 背包正好相反。请借助图 14-23 来理解两者的区别。
=== "<1>"
![完全背包的空间优化后的动态规划过程](unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step1.png)
![完全背包的空间优化后的动态规划过程](unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step1.png){ class="animation-figure" }
=== "<2>"
![unbounded_knapsack_dp_comp_step2](unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step2.png)
![unbounded_knapsack_dp_comp_step2](unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step2.png){ class="animation-figure" }
=== "<3>"
![unbounded_knapsack_dp_comp_step3](unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step3.png)
![unbounded_knapsack_dp_comp_step3](unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step3.png){ class="animation-figure" }
=== "<4>"
![unbounded_knapsack_dp_comp_step4](unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step4.png)
![unbounded_knapsack_dp_comp_step4](unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step4.png){ class="animation-figure" }
=== "<5>"
![unbounded_knapsack_dp_comp_step5](unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step5.png)
![unbounded_knapsack_dp_comp_step5](unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step5.png){ class="animation-figure" }
=== "<6>"
![unbounded_knapsack_dp_comp_step6](unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step6.png)
![unbounded_knapsack_dp_comp_step6](unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step6.png){ class="animation-figure" }
<p align="center"> 图 14-23 &nbsp; 完全背包的空间优化后的动态规划过程 </p>
@@ -666,7 +666,7 @@ $$
给定 $n$ 种硬币,第 $i$ 种硬币的面值为 $coins[i - 1]$ ,目标金额为 $amt$ **每种硬币可以重复选取**,问能够凑出目标金额的最少硬币个数。如果无法凑出目标金额则返回 $-1$ 。
![零钱兑换问题的示例数据](unbounded_knapsack_problem.assets/coin_change_example.png)
![零钱兑换问题的示例数据](unbounded_knapsack_problem.assets/coin_change_example.png){ class="animation-figure" }
<p align="center"> 图 14-24 &nbsp; 零钱兑换问题的示例数据 </p>
@@ -1070,49 +1070,49 @@ $$
图 14-25 展示了零钱兑换的动态规划过程,和完全背包非常相似。
=== "<1>"
![零钱兑换问题的动态规划过程](unbounded_knapsack_problem.assets/coin_change_dp_step1.png)
![零钱兑换问题的动态规划过程](unbounded_knapsack_problem.assets/coin_change_dp_step1.png){ class="animation-figure" }
=== "<2>"
![coin_change_dp_step2](unbounded_knapsack_problem.assets/coin_change_dp_step2.png)
![coin_change_dp_step2](unbounded_knapsack_problem.assets/coin_change_dp_step2.png){ class="animation-figure" }
=== "<3>"
![coin_change_dp_step3](unbounded_knapsack_problem.assets/coin_change_dp_step3.png)
![coin_change_dp_step3](unbounded_knapsack_problem.assets/coin_change_dp_step3.png){ class="animation-figure" }
=== "<4>"
![coin_change_dp_step4](unbounded_knapsack_problem.assets/coin_change_dp_step4.png)
![coin_change_dp_step4](unbounded_knapsack_problem.assets/coin_change_dp_step4.png){ class="animation-figure" }
=== "<5>"
![coin_change_dp_step5](unbounded_knapsack_problem.assets/coin_change_dp_step5.png)
![coin_change_dp_step5](unbounded_knapsack_problem.assets/coin_change_dp_step5.png){ class="animation-figure" }
=== "<6>"
![coin_change_dp_step6](unbounded_knapsack_problem.assets/coin_change_dp_step6.png)
![coin_change_dp_step6](unbounded_knapsack_problem.assets/coin_change_dp_step6.png){ class="animation-figure" }
=== "<7>"
![coin_change_dp_step7](unbounded_knapsack_problem.assets/coin_change_dp_step7.png)
![coin_change_dp_step7](unbounded_knapsack_problem.assets/coin_change_dp_step7.png){ class="animation-figure" }
=== "<8>"
![coin_change_dp_step8](unbounded_knapsack_problem.assets/coin_change_dp_step8.png)
![coin_change_dp_step8](unbounded_knapsack_problem.assets/coin_change_dp_step8.png){ class="animation-figure" }
=== "<9>"
![coin_change_dp_step9](unbounded_knapsack_problem.assets/coin_change_dp_step9.png)
![coin_change_dp_step9](unbounded_knapsack_problem.assets/coin_change_dp_step9.png){ class="animation-figure" }
=== "<10>"
![coin_change_dp_step10](unbounded_knapsack_problem.assets/coin_change_dp_step10.png)
![coin_change_dp_step10](unbounded_knapsack_problem.assets/coin_change_dp_step10.png){ class="animation-figure" }
=== "<11>"
![coin_change_dp_step11](unbounded_knapsack_problem.assets/coin_change_dp_step11.png)
![coin_change_dp_step11](unbounded_knapsack_problem.assets/coin_change_dp_step11.png){ class="animation-figure" }
=== "<12>"
![coin_change_dp_step12](unbounded_knapsack_problem.assets/coin_change_dp_step12.png)
![coin_change_dp_step12](unbounded_knapsack_problem.assets/coin_change_dp_step12.png){ class="animation-figure" }
=== "<13>"
![coin_change_dp_step13](unbounded_knapsack_problem.assets/coin_change_dp_step13.png)
![coin_change_dp_step13](unbounded_knapsack_problem.assets/coin_change_dp_step13.png){ class="animation-figure" }
=== "<14>"
![coin_change_dp_step14](unbounded_knapsack_problem.assets/coin_change_dp_step14.png)
![coin_change_dp_step14](unbounded_knapsack_problem.assets/coin_change_dp_step14.png){ class="animation-figure" }
=== "<15>"
![coin_change_dp_step15](unbounded_knapsack_problem.assets/coin_change_dp_step15.png)
![coin_change_dp_step15](unbounded_knapsack_problem.assets/coin_change_dp_step15.png){ class="animation-figure" }
<p align="center"> 图 14-25 &nbsp; 零钱兑换问题的动态规划过程 </p>
@@ -1450,7 +1450,7 @@ $$
给定 $n$ 种硬币,第 $i$ 种硬币的面值为 $coins[i - 1]$ ,目标金额为 $amt$ ,每种硬币可以重复选取,**问在凑出目标金额的硬币组合数量**。
![零钱兑换问题 II 的示例数据](unbounded_knapsack_problem.assets/coin_change_ii_example.png)
![零钱兑换问题 II 的示例数据](unbounded_knapsack_problem.assets/coin_change_ii_example.png){ class="animation-figure" }
<p align="center"> 图 14-26 &nbsp; 零钱兑换问题 II 的示例数据 </p>