BFS
BFS的典型案例就是走迷宫,每一步不是一直往前走,而是要考虑当前同步内有几个能走的,再从这么多个里面继续往下走。
广度优先搜索一层一层遍历,每一层遍历到的所有新节点,要用队列先存储起来以备下一层遍历的时候再遍历;而深度优先搜索在遍历到一个新节点时立马对新节点进行
遍历:从节点 0 出发开始遍历,得到到新节点 6 时,立马对新节点 6 进行遍历,得到新节点 4;如此反复以这种方式遍历新节点,直到没有新节点了,此时返回。返回到
根节点 0 的情况是,继续对根节点 0 进行遍历,得到新节点 2,然后继续以上步骤。
本题中,玩家在移动时会导致网格结构的变化,但实际上,玩家在最短路径中显然不会经过同一位置超过两次,因此最多消除k个障碍物等价于最多经过k个障碍物。
核心思想就是把每一个经过的点进行处理标记,如果到了终点马上返回则一定是最短路径。
class Solution { private int[][] dir = new int[][] {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; public int shortestPath(int[][] grid, int k) { int m = grid.length; int n = grid[0].length; boolean[][][] visited = new boolean[m][n][k + 1]; Queue<Point> queue = new LinkedList<>(); queue.add(new Point(0, 0, 0)); // **核心逻辑**:访问记录二维扩展为三维 visited[0][0][0] = true; int distance = 0; while (!queue.isEmpty()) { distance++; int size = queue.size(); for (int i = 0; i < size; i++) { Point point = queue.poll(); int x = point.x; int y = point.y; int z = point.z; // 找到障碍物 if (x == m - 1 && y == n - 1) { return distance -1; } // 4个方向移动 for (int j = 0; j < 4; j++) { int newX = x + dir[j][0]; int newY = y + dir[j][1]; int newZ = z; if (newX < 0 || newX >= m || newY < 0 || newY >= n) { continue; } // **核心逻辑**:有障碍物要对其进行处理,计算是否还能消除障碍物 if (grid[newX][newY] == 1) { // 没有消除 k 个障碍物,可以继续消除 if (z < k) { newZ = z + 1; } else { // 已经消除 k 个障碍物 continue; } } if (!visited[newX][newY][newZ]) { queue.add(new Point(newX, newY, newZ)); visited[newX][newY][newZ] = true; } } } } return -1; } class Point { int x; int y; int z; public Point(int x, int y, int z) { this.x = x; this.y = y; this.z = z; } } }
public int minPathLength(int[][] grids, int tr, int tc) { int[][] next = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; int m = grids.length, n = grids[0].length; Queue<Position> queue = new LinkedList<>(); queue.add(new Position(0, 0, 1)); while (!queue.isEmpty()) { Position pos = queue.poll(); for (int i = 0; i < 4; i++) { Position nextPos = new Position(pos.r + next[i][0], pos.c + next[i][1], pos.length + 1); if (nextPos.r < 0 || nextPos.r >= m || nextPos.c < 0 || nextPos.c >= n) continue; if (grids[nextPos.r][nextPos.c] != 1) continue; grids[nextPos.r][nextPos.c] = 0; if (nextPos.r == tr && nextPos.c == tc) return nextPos.length; queue.add(nextPos); } } return -1; } private class Position { int r, c, length; public Position(int r, int c, int length) { this.r = r; this.c = c; this.length = length; } }