package _2_1递归;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
class point{//一个点
int x;
int y;
int temp;
}
public class 宽搜BFS迷宫问题 {
public static int[][] a=new int[100][100];//迷宫
public static int[][] v=new int[100][100];//访问数组
public static int[] dx= {0,1,0,-1};//x方向上(竖着为x)扩展
public static int[] dy= {1,0,-1,0};//y方向上(横着为y)扩展
public static void main(String args[]) {
Scanner s=new Scanner(System.in);
int n,m;//n行m列的迷宫
n=s.nextInt();
m=s.nextInt();
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++){
a[i][j]=s.nextInt();
}
}
int startx,starty;//起点坐标
startx=s.nextInt();
starty=s.nextInt();
int p,q;//终点坐标
p=s.nextInt();
q=s.nextInt();
int flag=0;//判断能不能找到路径,初始设1,为找不到
//BFS
Queue<point> queue=new LinkedList<>();//创建一个队列
point start=new point();//定义一个起点
start.x=startx;
start.y=starty;
start.temp=0;
queue.add(start);//将起点入队,起点为队首
v[startx][starty]=1;//设置为该点已经访问
//将队首在四个方向上(右下左上)所扩展的点进行入队
while(!queue.isEmpty()) {//当队列为空时停止判断
int x=queue.peek().x;
int y=queue.peek().y;//取队首元素的的坐标
if(x==p&&y==q) {//如果到达终点,就输出+退出循环
flag=1;//找到这个路径了,flag设1
System.out.print(queue.peek().temp);
break;
}else {//如果还没有到达终点,就扩展四个方向上的点
for(int k=0;k<=3;k++) {
int tx = 0,ty = 0;//临时拓展方向
tx=x+dx[k];
ty=y+dy[k];
if(a[tx][ty]==1 && v[tx][ty]==0) {//如果迷宫里这个点可以走并且还没有被访问
//申请一个临时的结点用于入队
point temp = new point();
temp.x=tx;
temp.y=ty;
temp.temp=queue.peek().temp+1;//往前走了,所以步数+1
queue.add(temp);//将这个点放入队列
v[tx][ty]=1;//将这个点设置为已访问
}
}
queue.poll();//将队首元素出队
}
}
if(flag==0) {
System.out.print("no answer");
}
}
}
总结:
1、队列的运用,创建队列的方法为Queue<(数据类型)> queue=new LinkedList<>(),插入队列的方法为add(),放出队列的方法为poll(),取队头元素的方法为peek()。
2、迷宫的每一个点都是一个类,都有坐标变量x、y和步长变量step。要知道类怎么创建,以及类内成员变量怎么调用。
3、宽度优先搜索的思维,往右下左上四个方向扩展找值,判断是不是我们要找的点,不是就按队头元素扩展之后放入队列,队头元素出队。