From 444e0d1ad838f3fed5e19ae0498de950785b2002 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Tue, 21 Nov 2023 08:47:39 +0800 Subject: [PATCH] feat: update solutions to lc problem: No.2304 No.2304.Minimum Path Cost in a Grid --- .../README.md | 52 +++++++-------- .../README_EN.md | 64 +++++++++++-------- .../Solution.rs | 24 +++---- .../Solution.ts | 24 +++---- 4 files changed, 78 insertions(+), 86 deletions(-) diff --git a/solution/2300-2399/2304.Minimum Path Cost in a Grid/README.md b/solution/2300-2399/2304.Minimum Path Cost in a Grid/README.md index a750e9536e11c..3b4602a393a68 100644 --- a/solution/2300-2399/2304.Minimum Path Cost in a Grid/README.md +++ b/solution/2300-2399/2304.Minimum Path Cost in a Grid/README.md @@ -67,9 +67,9 @@ $$ 其中 $\text{moveCost}[grid[i - 1][k]][j]$ 表示从第 $i - 1$ 行第 $k$ 列移动到第 $i$ 行第 $j$ 列的代价。 -最终答案即为 $f[m - 1][j]$ 的最小值,其中 $j$ 的取值范围为 $[0, n - 1]$。 +最终答案即为 $\min_{0 \leq j < n} \{f[m - 1][j]\}$。 -由于每次转移只需要用到上一行的状态,因此可以将空间复杂度优化到 $O(n)$。 +由于每次转移只需要用到上一行的状态,因此我们可以使用滚动数组的方式,将空间复杂度优化到 $O(n)$。 时间复杂度 $O(m \times n^2)$,空间复杂度 $O(n)$。其中 $m$ 和 $n$ 分别为网格的行数和列数。 @@ -172,25 +172,21 @@ func minPathCost(grid [][]int, moveCost [][]int) int { ```rust impl Solution { pub fn min_path_cost(grid: Vec>, move_cost: Vec>) -> i32 { - let (m, n) = (grid.len(), grid[0].len()); - let mut dp = vec![0; n]; - for i in 0..m - 1 { - let mut counter = vec![i32::MAX; n]; + let m = grid.len(); + let n = grid[0].len(); + let mut f = grid[0].clone(); + + for i in 1..m { + let mut g: Vec = vec![i32::MAX; n]; for j in 0..n { - let val = grid[i][j]; for k in 0..n { - counter[k] = counter[k].min(val + move_cost[val as usize][k] + dp[j]); + g[j] = g[j].min(f[k] + move_cost[grid[i - 1][k] as usize][j] + grid[i][j]); } } - for j in 0..n { - dp[j] = counter[j]; - } + f.copy_from_slice(&g); } - let mut res = i32::MAX; - for i in 0..n { - res = res.min(dp[i] + grid[m - 1][i]); - } - res + + f.iter().cloned().min().unwrap_or(0) } } ``` @@ -199,23 +195,19 @@ impl Solution { ```ts function minPathCost(grid: number[][], moveCost: number[][]): number { - const m = grid.length, - n = grid[0].length; - let pre = grid[0].slice(); - for (let i = 1; i < m; i++) { - let next = new Array(n); - for (let j = 0; j < n; j++) { - const key = grid[i - 1][j]; - for (let k = 0; k < n; k++) { - let sum = pre[j] + moveCost[key][k] + grid[i][k]; - if (j == 0 || next[k] > sum) { - next[k] = sum; - } + const m = grid.length; + const n = grid[0].length; + const f = grid[0]; + for (let i = 1; i < m; ++i) { + const g: number[] = Array(n).fill(Infinity); + for (let j = 0; j < n; ++j) { + for (let k = 0; k < n; ++k) { + g[j] = Math.min(g[j], f[k] + moveCost[grid[i - 1][k]][j] + grid[i][j]); } } - pre = next; + f.splice(0, n, ...g); } - return Math.min(...pre); + return Math.min(...f); } ``` diff --git a/solution/2300-2399/2304.Minimum Path Cost in a Grid/README_EN.md b/solution/2300-2399/2304.Minimum Path Cost in a Grid/README_EN.md index f1cccaec1c0bf..4dc8e27c68203 100644 --- a/solution/2300-2399/2304.Minimum Path Cost in a Grid/README_EN.md +++ b/solution/2300-2399/2304.Minimum Path Cost in a Grid/README_EN.md @@ -49,6 +49,22 @@ So the total cost of this path is 5 + 1 = 6. ## Solutions +**Solution 1: Dynamic Programming** + +We define $f[i][j]$ to represent the minimum path cost from the first row to the $i$th row and $j$th column. Since we can only move from a column in the previous row to a column in the current row, the value of $f[i][j]$ can be transferred from $f[i - 1][k]$, where the range of $k$ is $[0, n - 1]$. Therefore, the state transition equation is: + +$$ +f[i][j] = \min_{0 \leq k < n} \{f[i - 1][k] + \text{moveCost}[grid[i - 1][k]][j] + grid[i][j]\} +$$ + +where $\text{moveCost}[grid[i - 1][k]][j]$ represents the cost of moving from the $k$th column of the $i - 1$th row to the $j$th column of the $i$th row. + +The final answer is $\min_{0 \leq j < n} \{f[m - 1][j]\}$. + +Since each transition only needs the state of the previous row, we can use a rolling array to optimize the space complexity to $O(n)$. + +The time complexity is $O(m \times n^2)$, and the space complexity is $O(n)$. Here, $m$ and $n$ are the number of rows and columns of the grid, respectively. + ### **Python3** @@ -144,25 +160,21 @@ func minPathCost(grid [][]int, moveCost [][]int) int { ```rust impl Solution { pub fn min_path_cost(grid: Vec>, move_cost: Vec>) -> i32 { - let (m, n) = (grid.len(), grid[0].len()); - let mut dp = vec![0; n]; - for i in 0..m - 1 { - let mut counter = vec![i32::MAX; n]; + let m = grid.len(); + let n = grid[0].len(); + let mut f = grid[0].clone(); + + for i in 1..m { + let mut g: Vec = vec![i32::MAX; n]; for j in 0..n { - let val = grid[i][j]; for k in 0..n { - counter[k] = counter[k].min(val + move_cost[val as usize][k] + dp[j]); + g[j] = g[j].min(f[k] + move_cost[grid[i - 1][k] as usize][j] + grid[i][j]); } } - for j in 0..n { - dp[j] = counter[j]; - } + f.copy_from_slice(&g); } - let mut res = i32::MAX; - for i in 0..n { - res = res.min(dp[i] + grid[m - 1][i]); - } - res + + f.iter().cloned().min().unwrap_or(0) } } ``` @@ -171,23 +183,19 @@ impl Solution { ```ts function minPathCost(grid: number[][], moveCost: number[][]): number { - const m = grid.length, - n = grid[0].length; - let pre = grid[0].slice(); - for (let i = 1; i < m; i++) { - let next = new Array(n); - for (let j = 0; j < n; j++) { - const key = grid[i - 1][j]; - for (let k = 0; k < n; k++) { - let sum = pre[j] + moveCost[key][k] + grid[i][k]; - if (j == 0 || next[k] > sum) { - next[k] = sum; - } + const m = grid.length; + const n = grid[0].length; + const f = grid[0]; + for (let i = 1; i < m; ++i) { + const g: number[] = Array(n).fill(Infinity); + for (let j = 0; j < n; ++j) { + for (let k = 0; k < n; ++k) { + g[j] = Math.min(g[j], f[k] + moveCost[grid[i - 1][k]][j] + grid[i][j]); } } - pre = next; + f.splice(0, n, ...g); } - return Math.min(...pre); + return Math.min(...f); } ``` diff --git a/solution/2300-2399/2304.Minimum Path Cost in a Grid/Solution.rs b/solution/2300-2399/2304.Minimum Path Cost in a Grid/Solution.rs index 6bf340a908638..41a9cabc3f180 100644 --- a/solution/2300-2399/2304.Minimum Path Cost in a Grid/Solution.rs +++ b/solution/2300-2399/2304.Minimum Path Cost in a Grid/Solution.rs @@ -1,23 +1,19 @@ impl Solution { pub fn min_path_cost(grid: Vec>, move_cost: Vec>) -> i32 { - let (m, n) = (grid.len(), grid[0].len()); - let mut dp = vec![0; n]; - for i in 0..m - 1 { - let mut counter = vec![i32::MAX; n]; + let m = grid.len(); + let n = grid[0].len(); + let mut f = grid[0].clone(); + + for i in 1..m { + let mut g: Vec = vec![i32::MAX; n]; for j in 0..n { - let val = grid[i][j]; for k in 0..n { - counter[k] = counter[k].min(val + move_cost[val as usize][k] + dp[j]); + g[j] = g[j].min(f[k] + move_cost[grid[i - 1][k] as usize][j] + grid[i][j]); } } - for j in 0..n { - dp[j] = counter[j]; - } - } - let mut res = i32::MAX; - for i in 0..n { - res = res.min(dp[i] + grid[m - 1][i]); + f.copy_from_slice(&g); } - res + + f.iter().cloned().min().unwrap_or(0) } } diff --git a/solution/2300-2399/2304.Minimum Path Cost in a Grid/Solution.ts b/solution/2300-2399/2304.Minimum Path Cost in a Grid/Solution.ts index 1adccecf9a1a5..f8fbe35ab443f 100644 --- a/solution/2300-2399/2304.Minimum Path Cost in a Grid/Solution.ts +++ b/solution/2300-2399/2304.Minimum Path Cost in a Grid/Solution.ts @@ -1,19 +1,15 @@ function minPathCost(grid: number[][], moveCost: number[][]): number { - const m = grid.length, - n = grid[0].length; - let pre = grid[0].slice(); - for (let i = 1; i < m; i++) { - let next = new Array(n); - for (let j = 0; j < n; j++) { - const key = grid[i - 1][j]; - for (let k = 0; k < n; k++) { - let sum = pre[j] + moveCost[key][k] + grid[i][k]; - if (j == 0 || next[k] > sum) { - next[k] = sum; - } + const m = grid.length; + const n = grid[0].length; + const f = grid[0]; + for (let i = 1; i < m; ++i) { + const g: number[] = Array(n).fill(Infinity); + for (let j = 0; j < n; ++j) { + for (let k = 0; k < n; ++k) { + g[j] = Math.min(g[j], f[k] + moveCost[grid[i - 1][k]][j] + grid[i][j]); } } - pre = next; + f.splice(0, n, ...g); } - return Math.min(...pre); + return Math.min(...f); }