This commit is contained in:
krahets
2024-04-09 20:43:40 +08:00
parent d8caf02e9e
commit a6adc8e20a
48 changed files with 1599 additions and 571 deletions

View File

@ -295,7 +295,7 @@ $$
dp[2] = cost[2]
// 状态转移:从较小子问题逐步求解较大子问题
for (i in 3..n) {
dp[i] = (min(dp[i - 1].toDouble(), dp[i - 2].toDouble()) + cost[i]).toInt()
dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i]
}
return dp[n]
}
@ -559,7 +559,7 @@ $$
var b = cost[2]
for (i in 3..n) {
val tmp = b
b = (min(a.toDouble(), tmp.toDouble()) + cost[i]).toInt()
b = min(a, tmp) + cost[i]
a = tmp
}
return b

View File

@ -349,11 +349,7 @@ $$
```kotlin title="min_path_sum.kt"
/* 最小路径和:暴力搜索 */
fun minPathSumDFS(
grid: Array<Array<Int>>,
i: Int,
j: Int
): Int {
fun minPathSumDFS(grid: Array<IntArray>, i: Int, j: Int): Int {
// 若为左上角单元格,则终止搜索
if (i == 0 && j == 0) {
return grid[0][0]
@ -366,7 +362,7 @@ $$
val up = minPathSumDFS(grid, i - 1, j)
val left = minPathSumDFS(grid, i, j - 1)
// 返回从左上角到 (i, j) 的最小路径代价
return (min(left.toDouble(), up.toDouble()) + grid[i][j]).toInt()
return min(left, up) + grid[i][j]
}
```
@ -711,8 +707,8 @@ $$
```kotlin title="min_path_sum.kt"
/* 最小路径和:记忆化搜索 */
fun minPathSumDFSMem(
grid: Array<Array<Int>>,
mem: Array<Array<Int>>,
grid: Array<IntArray>,
mem: Array<IntArray>,
i: Int,
j: Int
): Int {
@ -732,7 +728,7 @@ $$
val up = minPathSumDFSMem(grid, mem, i - 1, j)
val left = minPathSumDFSMem(grid, mem, i, j - 1)
// 记录并返回左上角到 (i, j) 的最小路径代价
mem[i][j] = (min(left.toDouble(), up.toDouble()) + grid[i][j]).toInt()
mem[i][j] = min(left, up) + grid[i][j]
return mem[i][j]
}
```
@ -1098,7 +1094,7 @@ $$
```kotlin title="min_path_sum.kt"
/* 最小路径和:动态规划 */
fun minPathSumDP(grid: Array<Array<Int>>): Int {
fun minPathSumDP(grid: Array<IntArray>): Int {
val n = grid.size
val m = grid[0].size
// 初始化 dp 表
@ -1115,8 +1111,7 @@ $$
// 状态转移:其余行和列
for (i in 1..<n) {
for (j in 1..<m) {
dp[i][j] =
(min(dp[i][j - 1].toDouble(), dp[i - 1][j].toDouble()) + grid[i][j]).toInt()
dp[i][j] = min(dp[i][j - 1], dp[i - 1][j]) + grid[i][j]
}
}
return dp[n - 1][m - 1]
@ -1500,7 +1495,7 @@ $$
```kotlin title="min_path_sum.kt"
/* 最小路径和:空间优化后的动态规划 */
fun minPathSumDPComp(grid: Array<Array<Int>>): Int {
fun minPathSumDPComp(grid: Array<IntArray>): Int {
val n = grid.size
val m = grid[0].size
// 初始化 dp 表
@ -1516,7 +1511,7 @@ $$
dp[0] = dp[0] + grid[i][0]
// 状态转移:其余列
for (j in 1..<m) {
dp[j] = (min(dp[j - 1].toDouble(), dp[j].toDouble()) + grid[i][j]).toInt()
dp[j] = min(dp[j - 1], dp[j]) + grid[i][j]
}
}
return dp[m - 1]

View File

@ -443,11 +443,7 @@ $$
dp[i][j] = dp[i - 1][j - 1]
} else {
// 最少编辑步数 = 插入、删除、替换这三种操作的最少编辑步数 + 1
dp[i][j] =
(min(
min(dp[i][j - 1].toDouble(), dp[i - 1][j].toDouble()),
dp[i - 1][j - 1].toDouble()
) + 1).toInt()
dp[i][j] = min(min(dp[i][j - 1], dp[i - 1][j]), dp[i - 1][j - 1]) + 1
}
}
}
@ -941,7 +937,7 @@ $$
dp[j] = leftup
} else {
// 最少编辑步数 = 插入、删除、替换这三种操作的最少编辑步数 + 1
dp[j] = (min(min(dp[j - 1].toDouble(), dp[j].toDouble()), leftup.toDouble()) + 1).toInt()
dp[j] = min(min(dp[j - 1], dp[j]), leftup) + 1
}
leftup = temp // 更新为下一轮的 dp[i-1, j-1]
}

View File

@ -361,13 +361,14 @@ comments: true
```kotlin title="climbing_stairs_backtrack.kt"
/* 回溯 */
fun backtrack(
choices: List<Int>,
choices: MutableList<Int>,
state: Int,
n: Int,
res: MutableList<Int>
) {
// 当爬到第 n 阶时,方案数量加 1
if (state == n) res[0] = res[0] + 1
if (state == n)
res[0] = res[0] + 1
// 遍历所有选择
for (choice in choices) {
// 剪枝:不允许越过第 n 阶
@ -382,7 +383,7 @@ comments: true
fun climbingStairsBacktrack(n: Int): Int {
val choices = mutableListOf(1, 2) // 可选择向上爬 1 阶或 2 阶
val state = 0 // 从第 0 阶开始爬
val res = ArrayList<Int>()
val res = mutableListOf<Int>()
res.add(0) // 使用 res[0] 记录方案数量
backtrack(choices, state, n, res)
return res[0]
@ -1054,7 +1055,7 @@ $$
fun climbingStairsDFSMem(n: Int): Int {
// mem[i] 记录爬到第 i 阶的方案总数,-1 代表无记录
val mem = IntArray(n + 1)
Arrays.fill(mem, -1)
mem.fill(-1)
return dfs(n, mem)
}
```
@ -1596,9 +1597,7 @@ $$
var a = 1
var b = 2
for (i in 3..n) {
val tmp = b
b += a
a = tmp
b += a.also { a = b }
}
return b
}

View File

@ -317,7 +317,7 @@ $$
val no = knapsackDFS(wgt, value, i - 1, c)
val yes = knapsackDFS(wgt, value, i - 1, c - wgt[i - 1]) + value[i - 1]
// 返回两种方案中价值更大的那一个
return max(no.toDouble(), yes.toDouble()).toInt()
return max(no, yes)
}
```
@ -692,7 +692,7 @@ $$
val no = knapsackDFSMem(wgt, value, mem, i - 1, c)
val yes = knapsackDFSMem(wgt, value, mem, i - 1, c - wgt[i - 1]) + value[i - 1]
// 记录并返回两种方案中价值更大的那一个
mem[i][c] = max(no.toDouble(), yes.toDouble()).toInt()
mem[i][c] = max(no, yes)
return mem[i][c]
}
```
@ -1052,8 +1052,7 @@ $$
dp[i][c] = dp[i - 1][c]
} else {
// 不选和选物品 i 这两种方案的较大值
dp[i][c] = max(dp[i - 1][c].toDouble(), (dp[i - 1][c - wgt[i - 1]] + value[i - 1]).toDouble())
.toInt()
dp[i][c] = max(dp[i - 1][c], dp[i - 1][c - wgt[i - 1]] + value[i - 1])
}
}
}
@ -1445,7 +1444,7 @@ $$
if (wgt[i - 1] <= c) {
// 不选和选物品 i 这两种方案的较大值
dp[c] =
max(dp[c].toDouble(), (dp[c - wgt[i - 1]] + value[i - 1]).toDouble()).toInt()
max(dp[c], dp[c - wgt[i - 1]] + value[i - 1])
}
}
}

View File

@ -327,11 +327,7 @@ $$
```kotlin title="unbounded_knapsack.kt"
/* 完全背包:动态规划 */
fun unboundedKnapsackDP(
wgt: IntArray,
value: IntArray,
cap: Int
): Int {
fun unboundedKnapsackDP(wgt: IntArray, value: IntArray, cap: Int): Int {
val n = wgt.size
// 初始化 dp 表
val dp = Array(n + 1) { IntArray(cap + 1) }
@ -343,8 +339,7 @@ $$
dp[i][c] = dp[i - 1][c]
} else {
// 不选和选物品 i 这两种方案的较大值
dp[i][c] = max(dp[i - 1][c].toDouble(), (dp[i][c - wgt[i - 1]] + value[i - 1]).toDouble())
.toInt()
dp[i][c] = max(dp[i - 1][c], dp[i][c - wgt[i - 1]] + value[i - 1])
}
}
}
@ -703,8 +698,7 @@ $$
dp[c] = dp[c]
} else {
// 不选和选物品 i 这两种方案的较大值
dp[c] =
max(dp[c].toDouble(), (dp[c - wgt[i - 1]] + value[i - 1]).toDouble()).toInt()
dp[c] = max(dp[c], dp[c - wgt[i - 1]] + value[i - 1])
}
}
}
@ -1154,8 +1148,7 @@ $$
dp[i][a] = dp[i - 1][a]
} else {
// 不选和选硬币 i 这两种方案的较小值
dp[i][a] = min(dp[i - 1][a].toDouble(), (dp[i][a - coins[i - 1]] + 1).toDouble())
.toInt()
dp[i][a] = min(dp[i - 1][a], dp[i][a - coins[i - 1]] + 1)
}
}
}
@ -1377,7 +1370,7 @@ $$
}
// 状态转移
for i := 1; i <= n; i++ {
// 序遍历
// 序遍历
for a := 1; a <= amt; a++ {
if coins[i-1] > a {
// 若超过目标金额,则不选硬币 i
@ -1568,7 +1561,7 @@ $$
val MAX = amt + 1
// 初始化 dp 表
val dp = IntArray(amt + 1)
Arrays.fill(dp, MAX)
dp.fill(MAX)
dp[0] = 0
// 状态转移
for (i in 1..n) {
@ -1578,7 +1571,7 @@ $$
dp[a] = dp[a]
} else {
// 不选和选硬币 i 这两种方案的较小值
dp[a] = min(dp[a].toDouble(), (dp[a - coins[i - 1]] + 1).toDouble()).toInt()
dp[a] = min(dp[a], dp[a - coins[i - 1]] + 1)
}
}
}
@ -2150,7 +2143,7 @@ $$
dp[0] = 1
// 状态转移
for i := 1; i <= n; i++ {
// 序遍历
// 序遍历
for a := 1; a <= amt; a++ {
if coins[i-1] > a {
// 若超过目标金额,则不选硬币 i