diff --git a/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/1.png b/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/1.png new file mode 100644 index 000000000..9b0e2ecf2 Binary files /dev/null and b/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/1.png differ diff --git a/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/2.png b/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/2.png new file mode 100644 index 000000000..6896e76dc Binary files /dev/null and b/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/2.png differ diff --git a/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/3.png b/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/3.png new file mode 100644 index 000000000..d8c7ecc70 Binary files /dev/null and b/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/3.png differ diff --git a/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/README.md b/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/README.md new file mode 100644 index 000000000..ed43cd192 --- /dev/null +++ b/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/README.md @@ -0,0 +1,55 @@ +# [1368.Minimum Cost to Make at Least One Valid Path in a Grid][title] + +## Description +Given an `m x n` grid. Each cell of the grid has a sign pointing to the next cell you should visit if you are currently in this cell. The sign of `grid[i][j]` can be: + +- `1` which means go to the cell to the right. (i.e go from `grid[i][j]` to `grid[i][j + 1]`) +- `2` which means go to the cell to the left. (i.e go from `grid[i][j]` to `grid[i][j - 1]`) +- `3` which means go to the lower cell. (i.e go from `grid[i][j]` to `grid[i + 1][j]`) +- `4` which means go to the upper cell. (i.e go from `grid[i][j]` to `grid[i - 1][j]`) + +Notice that there could be some signs on the cells of the grid that point outside the grid. + +You will initially start at the upper left cell (`0, 0`). A valid path in the grid is a path that starts from the upper left cell (`0, 0`) and ends at the bottom-right cell (`m - 1, n - 1`) following the signs on the grid. The valid path does not have to be the shortest. + +You can modify the sign on a cell with `cost = 1`. You can modify the sign on a cell **one time only**. + +Return the minimum cost to make the grid have at least one valid path. + +**Example 1:** + +![1](./1.png) + +``` +Input: grid = [[1,1,1,1],[2,2,2,2],[1,1,1,1],[2,2,2,2]] +Output: 3 +Explanation: You will start at point (0, 0). +The path to (3, 3) is as follows. (0, 0) --> (0, 1) --> (0, 2) --> (0, 3) change the arrow to down with cost = 1 --> (1, 3) --> (1, 2) --> (1, 1) --> (1, 0) change the arrow to down with cost = 1 --> (2, 0) --> (2, 1) --> (2, 2) --> (2, 3) change the arrow to down with cost = 1 --> (3, 3) +The total cost = 3. +``` + +**Example 2:** + +![2](./2.png) + +``` +Input: grid = [[1,1,3],[3,2,2],[1,1,4]] +Output: 0 +Explanation: You can follow the path from (0, 0) to (2, 2). +``` + +**Example 3:** + +![3](./3.png) + +``` +Input: grid = [[1,2],[4,3]] +Output: 1 +``` + +## 结语 + +如果你同我一样热爱数据结构、算法、LeetCode,可以关注我 GitHub 上的 LeetCode 题解:[awesome-golang-algorithm][me] + +[title]: https://leetcode.com/problems/minimum-cost-to-make-at-least-one-valid-path-in-a-grid +[me]: https://github.com/kylesliu/awesome-golang-algorithm diff --git a/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/Solution.go b/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/Solution.go index d115ccf5e..9547a6294 100755 --- a/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/Solution.go +++ b/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/Solution.go @@ -1,5 +1,78 @@ package Solution -func Solution(x bool) bool { +import "container/heap" + +// x, y, cost, dir +type heap1368 [][4]int + +func (h *heap1368) Len() int { + return len(*h) +} +func (h *heap1368) Swap(i, j int) { + (*h)[i], (*h)[j] = (*h)[j], (*h)[i] +} + +func (h *heap1368) Less(i, j int) bool { + return (*h)[i][2] < (*h)[j][2] +} +func (h *heap1368) Push(x any) { + *h = append(*h, x.([4]int)) +} + +func (h *heap1368) Pop() any { + old := *h + l := len(old) + x := old[l-1] + *h = old[:l-1] return x } + +var dir1368 = [4][2]int{ + {0, 1}, {0, -1}, {1, 0}, {-1, 0}, +} + +func Solution(grid [][]int) int { + m, n := len(grid), len(grid[0]) + if m == 1 && n == 1 { + return 0 + } + inf := m*n + 1 + dp := make([][]int, m) + for i := range m { + dp[i] = make([]int, n) + for j := range n { + dp[i][j] = inf + } + } + // 就是优先队列 + dp[0][0] = 0 + h := &heap1368{} + if grid[0][0]&1 == 0 { + dp[0][0] = 1 + heap.Push(h, [4]int{0, 0, 1, 1}) + heap.Push(h, [4]int{0, 0, 1, 3}) + } else { + heap.Push(h, [4]int{0, 0, 0, grid[0][0]}) + } + for h.Len() > 0 { + cur := heap.Pop(h).([4]int) + if cur[0] == m-1 && cur[1] == n-1 { + return cur[2] + } + for i, d := range dir1368 { + nx, ny := cur[0]+d[0], cur[1]+d[1] + if nx < m && nx >= 0 && ny < n && ny >= 0 { + cost := cur[2] + if i != cur[3]-1 { + cost++ + } + if dp[nx][ny] > cost { + dp[nx][ny] = cost + heap.Push(h, [4]int{nx, ny, cost, grid[nx][ny]}) + } + } + } + } + + return -1 +} diff --git a/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/Solution_test.go b/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/Solution_test.go index 14ff50eb4..fc46755fc 100755 --- a/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/Solution_test.go +++ b/leetcode/1301-1400/1368.Minimum-Cost-to-Make-at-Least-One-Valid-Path-in-a-Grid/Solution_test.go @@ -10,12 +10,12 @@ func TestSolution(t *testing.T) { // 测试用例 cases := []struct { name string - inputs bool - expect bool + inputs [][]int + expect int }{ - {"TestCase", true, true}, - {"TestCase", true, true}, - {"TestCase", false, false}, + {"TestCase1", [][]int{{1, 1, 1, 1}, {2, 2, 2, 2}, {1, 1, 1, 1}, {2, 2, 2, 2}}, 3}, + {"TestCase2", [][]int{{1, 1, 3}, {3, 2, 2}, {1, 1, 4}}, 0}, + {"TestCase3", [][]int{{1, 2}, {4, 3}}, 1}, } // 开始测试 @@ -30,10 +30,10 @@ func TestSolution(t *testing.T) { } } -// 压力测试 +// 压力测试 func BenchmarkSolution(b *testing.B) { } -// 使用案列 +// 使用案列 func ExampleSolution() { }