搜宽:每次取出队头元素,然后将该队头元素扩展出的所有元素放到队尾
需要的数组:
- 判重数组:st[] 一般是入队时判重(这样可以保证每一个点入队一次)
- queue 队列
宽搜一般模板
queue <- 初始状态入队 //先将某个初始状态入队
while(queue 非空)
{
t <- 队头 //每次取出队头元素放到t中
for(扩展t) //扩展t结点
{
ver <- 新节点
if(! st[ver]) //入队判重
{
ver -> 队尾 //新节点插入队尾
}
}
}
BFS能找到最少步数,也就是最短路径
因为BFS是按层来遍历的,会先把所有距离为0的点遍历完,然后再遍历所有距离为1的点,按这样的顺序来遍历的,再遍历所有距离为2的点,一层一层往外扩展,因此第一次扩展到终点时,必然是最短距离
import java.util.*;
/**
* 采用宽度搜索,一定能找到最小距离,因为是按照由近到远的距离来寻找,先遍历距离为0.为1,为2....依次遍历
* @author abc
*
*/
public class P1101 {
static final int N = 210;
static int r;//行数
static int c;//列数
static char[][] g = new char[N][N];//用来存放地图
static int[][] dis = new int[N][N];//用来表示距离原点的距离,同时可以充当判重数组,初始值为-1,若该值不等于-1,则表示,该点已经走过了
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int t = scan.nextInt();
while(t -- > 0) {
r = scan.nextInt();
c = scan.nextInt();
for(int i = 0;i < r;i ++) g[i] = scan.next().toCharArray();//按行输入字符串,并转换为字符数组
PII start = null, end = null; //定义起点、终点
for(int i = 0;i < r;i ++) {//遍历地图中的每一个点,寻找起始点和终止点的坐标
for(int j = 0;j < c;j ++) {
if(g[i][j] == 'S') start = new PII(i,j);
else if(g[i][j] == 'E') end = new PII(i,j);
}
}
int distance = bfs(start,end);//进行广度搜索,将起始点和终止点的坐标带入
if(distance == -1) System.out.println("oop!");
else System.out.println(distance);
}
}
public static int bfs(PII start,PII end) {
Queue<PII> q = new LinkedList<>();//创建一个队列,类型为PII
for(int i = 0;i < r;i ++) Arrays.fill(dis[i], -1);//首先将dis数组中都初始化为-1,用作判重数组
dis[start.x][start.y] = 0;//起始点也即是原点,距离为0
q.offer(start);//将起点放入队列头部
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};//创建两个数组,分别存放上下左右四个方向的坐标
while(!q.isEmpty()) {//若队列不为空,则进行操作
PII t = q.poll();//首先将队头元素取出并移除
for(int i = 0;i < 4;i ++) {//循环,让该点往上下左右四个方向走,扩展该点(队头元素)
int x = t.x + dx[i],y = t.y + dy[i];//坐标走到相应的地方
if( x < 0 || x >= r || y < 0|| y >= c) continue;//出界
if(g[x][y] == '#') continue;//撞墙
if(dis[x][y] != -1) continue;//已经走过的
dis[x][y] = dis[t.x][t.y] + 1;//前几个条件如果都不满足的话则可以向前行走,此时距离起点+1;
if(x == end.x && y == end.y) return dis[x][y];//若走到重点,则将距离原点的距离返回
q.offer(new PII(x,y));//若没到达,则将这个位置作为新的队列对头元素,并进行后面一系列的扩展操作
}
}
return -1;
}
}
对应C++中的Pairs<int, int>
class PII{
int x ;//每个点的横坐标
int y;//每个点的纵坐标
public PII(int x,int y) {
this.x = x;
this.y = y;
}
}