求迷宫最短路径【队列+回溯】

       求迷宫的最短路径(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出发,向四周搜索,标记搜索过的点……直至达到出口点(mn),然后从出口点沿搜索路径回溯直至入口。

 

注意点:

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));
			
		//}
		
	}
}

 

  • 6
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值