diff --git a/content/posts/leetcode.md b/content/posts/leetcode.md index c780b37..ff2a057 100644 --- a/content/posts/leetcode.md +++ b/content/posts/leetcode.md @@ -5677,3 +5677,127 @@ func getMaximumGold(grid [][]int) int { ### 总结 其实上面代码还有优化的空间, 在遍历数组并走所有路径的过程中, 显然有些路径是重复的, 可以再使用一个三维数组保存二维数组中某一位向四个方向走的路径得到的四个方向的最大值. 这样在遇到重复路径时直接返回值即可. 不用再次递归遍历. + +## day78 2024-05-15 + +### 2812. Find the Safest Path in a Grid + +You are given a 0-indexed 2D matrix grid of size n x n, where (r, c) represents: + +A cell containing a thief if grid[r][c] = 1 +An empty cell if grid[r][c] = 0 +You are initially positioned at cell (0, 0). In one move, you can move to any adjacent cell in the grid, including cells containing thieves. + +The safeness factor of a path on the grid is defined as the minimum manhattan distance from any cell in the path to any thief in the grid. + +Return the maximum safeness factor of all paths leading to cell (n - 1, n - 1). + +An adjacent cell of cell (r, c), is one of the cells (r, c + 1), (r, c - 1), (r + 1, c) and (r - 1, c) if it exists. + +The Manhattan distance between two cells (a, b) and (x, y) is equal to |a - x| + |b - y|, where |val| denotes the absolute value of val. + +![0515hZwTUxsfESZf](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0515hZwTUxsfESZf.png) + +### 题解 + +本题的安全因子定义为路径上的任一坐标到任何贼节点的最小曼哈顿距离. 因此应该从贼的节点出发, 通过BFS向外计算出每个节点到这个贼节点的距离, 通过对所有的贼节点进行BFS, 即可得到全部节点到任一贼节点的最小距离. 问题变为, 有了最小距离如何找到一条满足最小距离的可行路径. 可知我们要寻找的路径其路径上的所有点到贼的最小距离都应该大于或等于假设的最小距离, 否则这条路径的安全因子应该更小. 如何找到所有最小距离中可行的最大值? 可以通过从起点出发执行bfs寻找从(0,0)到(n-1,n-1)之间的可行路径, 在bfs过程中相邻节点的距离大于等于当前假设的最小距离节点才可达, 否则不可达, 如果相邻节点找不到可行路径则减小假设的最小值, 这里减小可以采用二分法进行增减. 如果找到了一条可行路径则增大假设的最小值再次判断是否有路径可达. 相当于在所有可行最小距离中二分查找到可行的最大值. 这样要比从最大的可行距离开始每次减少1直到找到最终的可行距离快得多. + +### 代码 + +```go +func maximumSafenessFactor(grid [][]int) int { + rowlen := len(grid) + collen := len(grid[0]) + stack := [][]int{} + + + for rowi,row := range grid{ + for coli, value := range row{ + if value == 1{ + grid[rowi][coli] = 0 + stack = append(stack, []int{rowi,coli}) + }else{ + grid[rowi][coli] = -1 + } + } + } + directions := [][]int{{-1,0},{1,0},{0,1},{0,-1}} + depth := 1 + for len(stack) > 0{ + for _,point := range stack{ + temprow := point[0] + tempcol := point[1] + for _, dir := range directions{ + temprow = point[0] + tempcol = point[1] + temprow += dir[0] + tempcol += dir[1] + if temprow >=0 && temprow < rowlen && tempcol >= 0 && tempcol < collen && grid[temprow][tempcol] == -1{ + grid[temprow][tempcol] = depth + stack = append(stack, []int{temprow,tempcol}) + } + } + stack = stack[1:] + } + depth++ + } + + max := 0 + for _,row := range grid{ + for _, value := range row{ + if value > max{ + max = value + } + } + } + + start := 0 + mid := 0 + result := 0 + for start <= max{ + mid = (start + max) / 2 + if grid[0][0] < mid || grid[rowlen-1][rowlen-1] < mid{ + max = mid - 1 + continue + } + if validpath(grid, rowlen, mid){ + result = mid + start = mid + 1 + }else{ + max = mid-1 + } + } + return result + +} + +func validpath(grid [][]int,rowlen int,mid int)bool{ + visited := make([][]bool, rowlen) + for i:=0;i 0{ + for _,point := range stack{ + temprow := point[0] + tempcol := point[1] + for _, dir := range directions{ + temprow = point[0] + tempcol = point[1] + temprow += dir[0] + tempcol += dir[1] + if temprow >=0 && temprow < rowlen && tempcol >= 0 && tempcol < rowlen && visited[temprow][tempcol] == false && grid[temprow][tempcol] >= mid{ + if temprow == rowlen-1 && tempcol == rowlen - 1{ + return true + } + visited[temprow][tempcol] = true + stack = append(stack, []int{temprow,tempcol}) + } + } + stack = stack[1:] + } + } + return false +} +```