求迷宫最短路径【队列+回溯】
求迷宫的最短路径(0表示通路,1表示受阻)
问题:有一个迷宫,求从入口到出口的最短路径,其中0表示通路,1表示受阻,规定向下是X轴,向右是Y轴
输入:第一个数迷宫x轴的长度,第二个数迷宫y轴的长度,紧接着入口点的坐标和出口的坐标,之后是一个迷宫
输出:迷宫所走的路径的坐标
样例:
INPUT:
6 8
1 1
6 8
0 1 1 1 0 1 1 1
1 0 1 0 1 0 1 0
0 1 0 0 1 1 1 1
0 1 1 1 0 0 1 1
1 0 0 1 1 0 0 0
0 1 1 0 0 1 1 0
OUT:
(1,1)-->(2,2)-->(3,3)-->(3,4)-->(4,5)-->(4,6)-->(5,7)-->(6,8)
基本思想:从迷宫入口(1,1)出发,向四周搜索,记下所有一次能通达的坐标p11,p12,…p1k,然后从p11,p12,…p1k出发,向四周搜索,标记搜索过的点……直至达到出口点(m,n),然后从出口点沿搜索路径回溯直至入口。
注意点:
1.为什么从(1,1)点出发而不从(0,0)点出发?
若从(0,0)点出发向四周八个点进行搜索是搜索不了的,其实就是为了代码的统一
2.为什么使用队列这种数据结构?为什么使用队列记录的路径是最短的呢?
1.仔细分析一下这个迷宫,我们从(1,1)点出发,到下一个点(2,2),在(2,2)这里有两种情况都应该记录下来,以此类推把之后的搜索到的记录都记录到最后,先搜索到的应该先进行继续搜索,这种逻辑结构符合队列的逻辑结构
2.对角线最短这应该大家都懂,假设有一个迷宫是这样的
序号为1的地方表示入口而序号为9的地方表示出口,显而易见这个迷宫其实全是通路的,从起点都能到达终点
从序号1向四周搜索,搜到的应该是序号2,4,5把这三个点保存到队列中,从序号2开始搜索到序号3保存到队列中,序号4也是一样,把7,8两个点加入到队列中,但是从5开始搜索的时候保存的是6,9两个点,最先找到终点的一定是5.因为2或者4还要很多步数一定是比序号5慢的
下面是代码:
package 队列的应用_搜迷宫最短路径;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class FindMinLoad {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int x = in.nextInt();//X轴长度
int y = in.nextInt();//Y轴
int[][] mg = new int[x+2][y+2];//迷宫
int Xrk = in.nextInt();//入口
int Yrk = in.nextInt();
int Xck = in.nextInt();//出口
int Yck = in.nextInt();
for (int i = 0; i < mg[0].length; i++) {
mg[0][i] = 1;
mg[x+1][i] = 1;
}
for (int i = 0; i < mg.length; i++) {
mg[i][0] = 1;
mg[i][y+1] = 1;
}
for (int i = 1; i < mg.length-1; i++) {
for (int j = 1; j < mg[i].length-1; j++) {
mg[i][j] = in.nextInt();
}
}
// for (int i = 0; i < mg.length; i++) {
// for (int j = 0; j < mg[i].length; j++) {
// System.out.print(mg[i][j]+" ");
// }
// System.out.println();
// }
//if(x==1 && y==1) {
//System.out.println("0");
//}else {
int[][] queue = new int[x*y][3];
queue[0][0] = Xrk;
queue[0][1] = Yrk;
queue[0][2] = -1;
int front = 0;
int rear = 1;
OUT:
while(front!=rear) {
mg[queue[front][0]][queue[front][1]] = 1;
for (int i = queue[front][0]-1; i <= queue[front][0]+1; i++) {
for (int j = queue[front][1]-1; j <= queue[front][1]+1; j++) {
if(mg[i][j]==0) {//通路记录下
queue[rear][0] = i;
queue[rear][1] = j;
queue[rear++][2] = front;
mg[i][j]=1;
if(i==Xck && j==Yck) {
break OUT;
}
}
}
}
//System.out.println((queue[rear-1][0]!=Yck)+" "+(queue[rear-1][1]!=Xck));
front++;
}
List<String> list = new ArrayList<String>();
for (int i = rear-1; i>=0; i--) {
//System.out.println("("+queue[i][0]+","+queue[i][1]+")");
list.add("("+queue[i][0]+","+queue[i][1]+")");
i = queue[i][2]+1;
}
for (int i = list.size()-1; i>0; i--) {
System.out.print(list.get(i)+"-->");
}
System.out.print(list.get(0));
//}
}
}