mirror of
https://github.com/krahets/hello-algo.git
synced 2025-12-19 07:17:54 +08:00
Add subtitles to docs
This commit is contained in:
@@ -26,6 +26,8 @@ $$
|
||||
dp[i, c] = \max(dp[i-1, c], dp[i, c - wgt[i-1]] + val[i-1])
|
||||
$$
|
||||
|
||||
### 代码实现
|
||||
|
||||
对比两道题目的动态规划代码,状态转移中有一处从 $i-1$ 变为 $i$ ,其余完全一致。
|
||||
|
||||
=== "Java"
|
||||
@@ -94,6 +96,8 @@ $$
|
||||
[class]{}-[func]{unboundedKnapsackDP}
|
||||
```
|
||||
|
||||
### 状态压缩
|
||||
|
||||
由于当前状态是从左边和上边的状态转移而来,**因此状态压缩后应该对 $dp$ 表中的每一行采取正序遍历**,这个遍历顺序与 0-1 背包正好相反。请通过以下动画来理解为什么要改为正序遍历。
|
||||
|
||||
=== "<1>"
|
||||
@@ -221,7 +225,9 @@ $$
|
||||
|
||||
当目标金额为 $0$ 时,凑出它的最少硬币个数为 $0$ ,即所有 $dp[i, 0]$ 都等于 $0$ 。当无硬币时,**无法凑出任意 $> 0$ 的目标金额**,即是无效解。为使状态转移方程中的 $\min()$ 函数能够识别并过滤无效解,我们考虑使用 $+ \infty$ 来表示它们,即令所有 $dp[0, a]$ 都等于 $+ \infty$ 。
|
||||
|
||||
以上做法仅适用于 Python 语言,因为大多数编程语言并未提供 $+ \infty$ 变量,所以只能使用整型 `int` 的最大值,而这又会导致大数越界:**当 $dp[i, a - coins[i-1]]$ 是无效解时,再执行 $+ 1$ 操作会发生溢出**。
|
||||
### 代码实现
|
||||
|
||||
然而,大多数编程语言并未提供 $+ \infty$ 变量,因此只能使用整型 `int` 的最大值来代替,而这又会导致大数越界:**当 $dp[i, a - coins[i-1]]$ 是无效解时,再执行 $+ 1$ 操作会发生溢出**。
|
||||
|
||||
为解决该问题,我们采用一个不可能达到的大数字 $amt + 1$ 来表示无效解,因为凑出 $amt$ 的硬币个数最多为 $amt$ 个。
|
||||
|
||||
@@ -340,6 +346,8 @@ $$
|
||||
=== "<15>"
|
||||

|
||||
|
||||
### 状态压缩
|
||||
|
||||
由于零钱兑换和完全背包的状态转移方程如出一辙,因此状态压缩方式也相同。
|
||||
|
||||
=== "Java"
|
||||
@@ -426,6 +434,8 @@ $$
|
||||
|
||||
当目标金额为 $0$ 时,无需选择任何硬币即可凑出目标金额,因此应将所有 $dp[i, 0]$ 都初始化为 $1$ 。当无硬币时,无法凑出任何 $>0$ 的目标金额,因此所有 $dp[0, a]$ 都等于 $0$ 。
|
||||
|
||||
### 代码实现
|
||||
|
||||
=== "Java"
|
||||
|
||||
```java title="coin_change_ii.java"
|
||||
@@ -492,6 +502,8 @@ $$
|
||||
[class]{}-[func]{coinChangeIIDP}
|
||||
```
|
||||
|
||||
### 状态压缩
|
||||
|
||||
状态压缩处理方式相同,删除硬币维度即可。
|
||||
|
||||
=== "Java"
|
||||
|
||||
Reference in New Issue
Block a user