看了其他人AC的代码,一脸懵逼,这都是啥玩意儿。参考哔哩哔哩题目讲解的思路,自己写了一下。
import java.util.*;
public class Main {
static final int VISITED = -1;
static final int UNVISITED = 0;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int r1 = sc.nextInt();
int r2 = sc.nextInt();
// 漂亮美眉和猫咪的坐标
int px = 0, py = 0, mx = 0, my = 0;
sc.nextLine();
int[][] maze = new int[n][m];
for (int i = 0; i < n; i++) {
char[] chars = sc.nextLine().toCharArray();
for (int j = 0; j < m; j++) {
switch (chars[j]) {
case 'P':
px = i;
py = j;
break;
case 'M':
mx = i;
my = j;
break;
case '*':
maze[i][j] = -1;
break;
default:
break;
}
}
}
if (bfs(maze, px, py, mx, my, r1, r2)) {
int steps = bfs(maze, mx, my);
System.out.println(steps == Integer.MAX_VALUE ? -1 : steps);
} else {
System.out.println(-1);
}
}
static class Point {
int x, y, step;
public Point(int x, int y, int step) {
this.x = x;
this.y = y;
this.step = step;
}
}
static public boolean bfs(int[][] maze, int px, int py, int mx, int my, int r1, int r2) {
// 可以移动的方向 上下左右
int[] dx = {1, -1, 0, 0};
int[] dy = {0, 0, 1, -1};
int m = maze.length;
int n = maze[0].length;
// 在不在猫的嗅觉范围内
boolean cat = false;
Queue<Point> queue = new LinkedList<>();
// 入口入队
queue.offer(new Point(px, py, 0));
// 标记为已访问过
maze[px][py] = VISITED;
while (!queue.isEmpty()) {
Point poll = queue.poll();
// 枚举四个方向
for (int k = 0; k < dx.length; k++) {
int x = poll.x + dx[k];
int y = poll.y + dy[k];
// 没越界
boolean isNotOutOfBound = x >= 0 && x < m && y >= 0 && y < n;
// 没有访问过 且 在漂亮妹妹的活动范围内
if (isNotOutOfBound && maze[x][y] == UNVISITED && isInTheRange(x, y, px, py, r1)) {
// 标记为已访问过
maze[x][y] = VISITED;
// 在猫的嗅觉范围内
if (isInTheRange(x, y, mx, my, r2)) {
cat = true;
// 更新这个地图 maze[i][j]的值为-1表示"已经访问过"或者"障碍物" 总之不再访问
// 大于0 表示漂亮妹妹走到这里需要几步
maze[x][y] = poll.step + 1;
continue;
}
queue.offer(new Point(x, y, poll.step + 1));
}
}
}
return cat;
}
static public int bfs(int[][] maze, int mx, int my) {
// 可以移动的方向 上下左右
int[] dx = {1, -1, 0, 0};
int[] dy = {0, 0, 1, -1};
int m = maze.length;
int n = maze[0].length;
Queue<Point> queue = new LinkedList<>();
// 入口入队
queue.offer(new Point(mx, my, 0));
// 标记为已访问过
maze[mx][my] = VISITED;
int min = Integer.MAX_VALUE;
while (!queue.isEmpty()) {
Point poll = queue.poll();
// 枚举四个方向
for (int k = 0; k < dx.length; k++) {
int x = poll.x + dx[k];
int y = poll.y + dy[k];
// 没越界
boolean isNotOutOfBound = x >= 0 && x < m && y >= 0 && y < n;
// 猫咪只要嗅到了小鱼干,就可以到处跑,没有距离限制
if (isNotOutOfBound && maze[x][y] != VISITED) {
// 如果这是漂亮美眉可达的地方
if (maze[x][y] > 0) {
min = Math.min(min, maze[x][y] + poll.step + 1);
} else {
// 标记为已访问过
maze[x][y] = VISITED;
}
queue.offer(new Point(x, y, poll.step + 1));
}
}
}
return min;
}
static boolean isInTheRange(int x1, int y1, int x2, int y2, int r) {
return Math.abs(x1 - x2) + Math.abs(y1 - y2) <= r;
}
}