思路①:可以分别对每个领主所在地进行广搜,搜到第一个感染源时就是被感染时间,但是用java会MLE,因此行不通
思路②:可以同时对每个感染源所在地进行广搜,并把每一次的每一个感染源在每一层搜到相应的地点的所需时间记录在n*m的数组里,这样得到的数组就是各个地点被感染的时间,最后输出各个领主所在地的感染时间就行了,这种方法比思路①快很多,空间也节省很多。
package search;
import java.awt.Point;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.LinkedList;
import java.util.Queue;
public class P1332 {
static int n, m, a, b, arr[][];
static int[] xx = { 0, 0, 1, -1 };
static int[] yy = { 1, -1, 0, 0 };
static Queue<Point> p = new LinkedList<Point>();
static boolean[][] vis = new boolean[505][505];
public static void main(String[] args) throws IOException {
StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
st.nextToken();
n = (int) st.nval;
st.nextToken();
m = (int) st.nval;
st.nextToken();
a = (int) st.nval;
st.nextToken();
b = (int) st.nval;
arr = new int[n + 1][m + 1];
for (int i = 0; i < a; i++) {
st.nextToken();
int r = (int) st.nval;
st.nextToken();
int c = (int) st.nval;
p.add(new Point(r, c));
arr[r][c] = 0;//感染源所在点感染时间为0
vis[r][c] = true;//设为已访问
}
bfs();
for (int i = 0; i < b; i++) {
st.nextToken();
int r = (int) st.nval;
st.nextToken();
int c = (int) st.nval;
System.out.println(arr[r][c]);
}
}
//同时对所有感染源进行广搜
public static void bfs() {
while (!p.isEmpty()) {
Point pp = p.poll();
for (int i = 0; i < 4; i++) {
int row = pp.x + xx[i], col = pp.y + yy[i];
if (row >= 1 && row <= n && col >= 1 && col <= m && !vis[row][col]) {
p.add(new Point(row, col));
arr[row][col] = arr[pp.x][pp.y] + 1;//在起始点步数基础上+1
vis[row][col] = true;
}
}
}
}
}