此文章用来记录遇到的经典的从某个点到达某个边界或者指定点的BFS题目,将持续更新
class Solution {
// n,m代表给定二维数组或者二重List>这种的长和宽
// x0,y0代表给定的起点坐标
// dir数组代表的是进行上下左右搜索的坐标方向
int n;
int m;
int x0;
int y0;
int[][] dir = {{1,0}, {-1, 0}, {0, -1}, {0,1}};
public int nearestExit(char[][] maze, int[] entrance) {
n = maze.length;
m = maze[0].length;
x0 = entrance[0];
y0 = entrance[1];
return bfs(maze, x0, y0);
}
public int bfs(char[][] maze, int i, int j) {
Queue<int[]> q = new ArrayDeque<>();
// 添加起始点坐标以及耗费步数
q.offer(new int[]{x0, y0, 0});
// 已经遍历过起始点,标记起始点为不可达
maze[x0][y0] = '+';
while (!q.isEmpty()) {
int[] arr = q.poll();
int tx = arr[0];
int ty = arr[1];
int step = arr[2];
// 如果(tx,ty)坐标与(i,j)坐标不是同一个坐标,且(tx,ty)已经在边界,那就直接返回step步数
if ( !(tx == i && ty == j) && (tx == 0 || tx == n - 1|| ty == 0 || ty == m - 1) ) {
return step;
}
// 进行方向遍历
for (int k = 0 ; k < 4; k++) {
// 上下左右方向,其中dx代表横坐标,dy代表纵坐标
int dx = tx + dir[k][0];
int dy = ty + dir[k][1];
// 如果(dx,dy)在(0,0)~(n - 1, m - 1)范围内,且(dx,dy)是可以继续遍历的,那就将当前坐标(dx,dy)添加到队列里,并标记当前坐标已经遍历过了
if (dx >= 0 && dx < n && dy >= 0 && dy < m && maze[dx][dy] == '.') {
q.offer(new int[]{dx, dy, step + 1});
maze[dx][dy] = '+';
}
}
}
// 如果无法到达指定位置,那就返回-1
return -1;
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Queue;
public class Main {
static int n;
static int m;
static int x0;
static int y0;
static Queue<int[]> q = new ArrayDeque<>();
static int[][] f;
static int[][] dir = {{0,1}, {0,-1}, {1,0}, {-1,0}};
static int[][] directions = {{-1, 2},{-2, 1},{-2, -1}, {-1, -2}, {1, 2},{2, 1}, {2, -1}, {1,-2} };
static boolean[][] vis;
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String[] s = reader.readLine().split(" ");
n = Integer.parseInt(s[0]);
m = Integer.parseInt(s[1]);
x0 = Integer.parseInt(s[2]);
y0 = Integer.parseInt(s[3]);
vis = new boolean[n + 10][m + 10];
f = new int[n + 10][m + 10];
for (int[] x : f) {
Arrays.fill(x, -1);
}
// x0, y0添加到队列,且标记当前(x0,y0)已经遍历过了
q.offer(new int[]{x0, y0});
f[x0][y0] = 0;
vis[x0][y0] = true;
bfs(x0, y0);
for (int i = 1 ; i <= n ; i++) {
for (int j = 1; j <= m ; j++) {
System.out.printf("%-5d",f[i][j]);
}
if (i != n) {
System.out.println();
}
}
}
public static void bfs(int i,int j) {
while (!q.isEmpty()) {
int[] arr = q.poll();
int tx = arr[0];
int ty = arr[1];
for (int k = 0; k < directions.length; k++) {
int dx = tx + directions[k][0];
int dy = ty + directions[k][1];
// 判断符合可以继续遍历到的添加到队列,同时可以继续遍历到的步数为上次可以遍历到的位置(tx,ty)的步数加1
if (dx >= 1 && dx <= n && dy >=1 && dy <= m && !vis[dx][dy]) {
q.offer(new int[]{dx, dy});
vis[dx][dy] = true;
f[dx][dy] = f[tx][ty] + 1;
}
}
}
}
}
class Read {
StreamTokenizer st = new StreamTokenizer(new InputStreamReader(System.in));
public int nextInt() throws IOException {
st.nextToken();
return (int) st.nval;
}
public double nextDouble() throws IOException {
st.nextToken();
return st.nval;
}
public String nextString() throws IOException {
st.nextToken();
return st.sval;
}
}
《爱与愁的故事第三弹·shopping》娱乐章。
调调口味来道水题。
爱与愁大神坐在公交车上无聊,于是玩起了手机。一款奇怪的游戏进入了爱与愁大神的眼帘:***(游戏名被打上了马赛克)。这个游戏类似象棋,但是只有黑白马各一匹,在点x1,y1和x2,y2上。它们得从点x1,y1和x2,y2走到1,1。这个游戏与普通象棋不同的地方是:马可以走“日”,也可以像象走“田”。现在爱与愁大神想知道两匹马到1,1的最少步数,你能帮他解决这个问题么?
第1行:两个整数x1,y1
第2行:两个整数x2,y2
第1行:黑马到1,1的步数
第2行:白马到1,1的步数
12 16
18 10
8
9
100%数据:x1,y1,x2,y2<=20
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Queue;
public class Main {
static int x0;
static int y0;
static int x1;
static int y1;
static int[][] dir = {{1, -2}, {1, 2}, {-1, -2}, {-1, 2}, {2, -1}, {2, 1}, {-2, -1}, {-2, 1},{2,2}, {2,-2},{-2,2},{-2,-2}};
static int N = 60;
static boolean[][] vis = new boolean[N][N];
static Queue<int[]> q = new ArrayDeque<>();
public static void main(String[] args) throws IOException {
Read read = new Read();
x0 = read.nextInt();
y0 = read.nextInt();
x1 = read.nextInt();
y1 = read.nextInt();
System.out.println(bfs(1,1, x0, y0));
while (!q.isEmpty()) {
q.poll();
}
for (boolean[] v : vis) {
Arrays.fill(v, false);
}
System.out.println(bfs(1,1, x1, y1));
}
public static int bfs(int i, int j, int x, int y) {
q.offer(new int[]{i, j, 0});
vis[i][j] = true;
while (!q.isEmpty()) {
int[] arr = q.poll();
int tx = arr[0];
int ty = arr[1];
int step = arr[2];
for (int k = 0; k < dir.length; k++) {
int dx = tx + dir[k][0];
int dy = ty + dir[k][1];
if (dx >= 1 && dx <= 50 && dy >= 1 && dy <= 50 && !vis[dx][dy]) {
q.offer(new int[]{dx, dy, step + 1});
vis[dx][dy] = true;
}
if (tx == x && ty == y) {
return step;
}
}
}
return -1;
}
}
class Read {
StreamTokenizer st = new StreamTokenizer(new InputStreamReader(System.in));
public int nextInt() throws IOException {
st.nextToken();
return (int) st.nval;
}
public double nextDouble() throws IOException {
st.nextToken();
return st.nval;
}
public String nextString() throws IOException {
st.nextToken();
return st.sval;
}
}
《爱与愁的故事第三弹·shopping》最终章。
爱与愁大神买完东西后,打算坐车离开中山路。现在爱与愁大神在x1,y1处,车站在x2,y2处。现在给出一个n×n(n<=1000)的地图,0表示马路,1表示店铺(不能从店铺穿过),爱与愁大神只能垂直或水平着在马路上行进。爱与愁大神为了节省时间,他要求最短到达目的地距离(a[i][j]距离为1)。你能帮他解决吗?
第1行:一个数 n
第2行~第n+1行:整个地图描述(0表示马路,1表示店铺,注意两个数之间没有空格)
第n+2行:四个数 x1,y1,x2,y2
只有1行:最短到达目的地距离
3
001
101
100
1 1 3 3
4
20%数据:n<=100
100%数据:n<=1000
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.ArrayDeque;
import java.util.Queue;
public class Main {
static int n;
static int N = 1010;
static int[][] arr = new int[N][N];
static boolean[][] vis = new boolean[N][N];
static int[][] dir = {{1,0}, {-1,0}, {0,1}, {0,-1}};
static Queue<int[]> q = new ArrayDeque<>();
static int x0;
static int y0;
static int x;
static int y;
public static void main(String[] args) throws IOException {
BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(read.readLine());
for (int i = 1; i <= n; i++) {
String s = read.readLine();
for (int j = 1; j <= n; j++) {
arr[i][j] = s.charAt(j - 1) - '0';
}
}
String[] num = read.readLine().split(" ");
x0 = Integer.parseInt(num[0]);
y0 = Integer.parseInt(num[1]);
x = Integer.parseInt(num[2]);
y = Integer.parseInt(num[3]);
q.offer(new int[]{x0, y0, 0});
int res = dfs();
System.out.println(res);
}
public static int dfs() {
while (!q.isEmpty()) {
int[] a = q.poll();
int tx = a[0];
int ty = a[1];
int step = a[2];
if (arr[tx][ty] == 1) {
continue;
}
if (tx == x && ty == y) {
return step;
}
vis[tx][ty] = true;
for (int k = 0; k < 4; k++) {
int dx = tx + dir[k][0];
int dy = ty + dir[k][1];
if (dx >= 1 && dx <= n && dy >= 0 && dy <= n && !vis[dx][dy] && arr[dx][dy] == 0) {
q.offer(new int[]{dx, dy, step + 1});
vis[dx][dy] = true;
}
}
}
return -1;
}
}