DFS和BFS下的迷宫问题

深度优先搜索(DFS)

类似于数的先根遍历,是数的先根遍历的推广。假设初始状态是图中所有的顶点都未曾被访问,则深度优先搜索可以从图中的某个顶点出发,访问此顶点,然后依次从v未被访问的邻接点出发深度优先遍历图,直至图中所有和v相通的顶点都被访问到。若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作为起始点,重复上诉过程,直到图中所有的顶点都被访问到为止。
在这里插入图片描述

广度优先搜索(BFS)

类似于树的按层次遍历的过程。假设从图中某顶点v出发,在访问了v之后依次访问v的各个未曾访问的邻接点,然后分别从这些邻接点出发依次访问他们的邻接点,并使 “先被访问的邻接点”先于“后被访问的邻接点” ,直到图中所有已被访问的顶点的邻接点都被访问到。若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作为起始点,重复上诉过程,直到图中所有的顶点都被访问到为止。换句话说,广度优先搜索遍历图的过程是以v为起始点,由近至远,依次访问和v有路径相通且路径长度为1,2,3…的顶点。
在这里插入图片描述综上所诉,由于各自搜素的特性的区别。深度优先搜索(DFS)往往需要配合堆栈的使用,广度优先搜索(BFS)往往需要配合队列的使用.

迷宫问题

下图给出了一个迷宫的平面图,其中标记为 1 的为障碍,标记为 0 的为可以通行的地方。
010000
000100
001001
110000
迷宫的入口为左上角,出口为右下角,在迷宫中,只能从一个位置走到这个它的上、下、左、右四个方向之一。对于上面的迷宫,从入口开始,可以按DRRURRDDDR 的顺序通过迷宫,一共 10 步。其中 D、U、L、R 分别表示向下、向上、向左、向右走。

分析解答:
利用 深度优先搜索(DFS) 可以求出迷宫的所有路径中的一条路径,如果要求出迷宫的所有路径则还需要配合"回溯法"。
在这里插入图片描述上图为DFS求解迷宫路径的过程,关键是要配合栈的使用,以及将走过的地方进行标记,防止在探索迷宫时进入死循环。

import java.util.Stack;

public class Draft {
	public static void main(String[] args) {
		// 创建一个方向数组,其优先级为"下右左上",这里要注意的是,x,y是行列坐标,和直角坐标系的移动是有差异的
		int[][] direction = new int[][] { { 1, 0 }, { 0, -1 }, { -1, 0 }, { 0, 1 } };
		// 迷宫的地图信息,我们在原有的地图的基础上在外围添加一圈墙壁,1 表示墙壁
		int[][] graph = new int[][] { { 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 0, 1, 0, 0, 0, 0, 1 },
				{ 1, 0, 0, 0, 1, 0, 0, 1 }, { 1, 0, 0, 1, 0, 0, 1, 1 }, { 1, 1, 1, 0, 0, 0, 0, 1 },
				{ 1, 1, 1, 1, 1, 1, 1, 1 } };

		Stack<GPS> path = new Stack<>(); // 创建一个栈用来记录走过的路径
		boolean flag = false;            // 置标记flag判断迷宫是否有解

		int x = 1, y = 1,D=-1; // 初始化起点的位置信息,将起点压入栈中
		graph[x][y] = -1; // 标记该位置
		GPS startGps = new GPS(x, y, D);
		path.push(startGps);

		loop: while (!path.isEmpty()) {
			GPS tempGps = path.pop();
			x = tempGps.x;
			y = tempGps.y;
			D = tempGps.d +1;

			while(D<4){
				int row = x + direction[D][0];
				int col = y + direction[D][1];

				if (graph[row][col] == 0) {
					path.push(new GPS(x, y, D)); // 将当前的位置信息压入栈中
					
					x = row;     // 走到下一个节点,并将该结点标记
					y = col;
					graph[x][y] = -1;

					if (x == 4 && y == 6) {
						path.push(new GPS(4, 6, 0)); // 将终点压栈
						flag = true;                 // 修改标记的值,表示迷宫有解
						break loop;                  // 跳出标记所在的循环
					} else {
						D = 0;
					}
				} else {
					D++;
				}
			}
		}

		if (flag) {
			System.out.println("该迷宫有解");
			Stack<GPS> realPath = new Stack<>(); // 将栈逆序输出即可得路径
			while (!path.isEmpty()) {
				realPath.push(path.pop());
			}
			while (!realPath.isEmpty()) {
				GPS g = realPath.pop();
				System.out.print("(" + g.x + "," + g.y + ")"+"  ");
			}
		} else {
			System.out.println("该迷宫无解");
		}
	}
}

// 表示当前所处的位置信息
class GPS {
	int x;   // 当前位置的行坐标
	int y;   // 当前位置的列坐标
	int d;   // 表示下一个可行位置的方向

	// 全参数的构造方法
	public GPS(int x, int y,int d) {
		this.x = x;
		this.y = y;
		this.d = d;
	}
}

利用 BFS(广度优先搜索) 求迷宫的一条最短路径,其关键在于配合队列的使用,以及对走过位置的标记。
在这里插入图片描述如上图所示为广度优先搜索迷宫的过程,代码如下


import java.util.LinkedList;
/*
广度优先搜索解决,找出迷宫的最短路径
*/
public class Maze_BFS {
	public static void main(String[] args) {
		
		//创建一个方向数组,方向的优先级为 "下左上右"
		 Direction[] di = new Direction[] {new Direction(1,0),new Direction(0,-1),new Direction(-1,0),new Direction(0,1)};
		 
		 //创建一个字符串数组,其中 D、U、L、R 分别表示向下、向上、向左、向右走。
		 StringBuffer[] step = new StringBuffer[] {new StringBuffer("D"),new StringBuffer("L"),new StringBuffer("U"),new StringBuffer("R")};
		 
		 //创建队列,LinkedList为Queue<>接口的实现类
		 LinkedList<GPS> quene = new LinkedList<>(); 
		 
		 //迷宫地图,起点为(1,1),终点为(4,6)
		 int[][] graph = new int[][] {{1,1,1,1,1,1,1,1},{1,0,1,0,0,0,0,1},{1,0,0,0,1,0,0,1},
				                      {1,0,0,1,0,0,1,1},{1,1,1,0,0,0,0,1},{1,1,1,1,1,1,1,1}};
	     //创建一个标识符,判断迷宫是否有解
	     boolean b = false;
				                      
         int x=1,y=1,stepNumber=0;
         String startStep = "";
         GPS temp = new GPS(x,y,stepNumber,startStep);  //将起始点的信息加入队列
         graph[x][y] = -1;                              //将当前位置标记为已经走过
         quene.addLast(temp);
         
         Loop:while(!quene.isEmpty()) {
        	 
        	 temp = quene.poll() ;    //弹出队头元素进行扩展
        	 
        	 for(int i=0;i<4;i++) {    //按照优先级"下左上右",依次进行扩展
        		 int row = temp.x + di[i].inc_x;
        		 int col = temp.y + di[i].inc_y;
        		 StringBuffer ts = step[i]; //当前方向的字母表示
        		 
        		 if(graph[row][col] == 0) {
        			 int tempStepNumber = temp.stepNumber+1;
        			 String tempStepPath = temp.stb + ts;  
        			 quene.addLast(new GPS(row,col,tempStepNumber,tempStepPath)); //符合条件的坐标加入队列
        			 
        			 graph[row][col] = -1;   //将该结点的值设为-1,扩展该结点
        			 
        			 if(row==4 && col==6) {  //判断是否到达了终点
        				 b = true;
        				 break Loop;        //跳出标记所在的循环
        			 }
        		 }
        	 }     	 
         }
         
         if (b) {
        	 System.out.println("该迷宫有解");
        	 System.out.println("走出迷宫至少需要: " + quene.getLast().stepNumber + " 步");  //队尾元素存储的信息即是答案
        	 System.out.println("最短路径的走法: " + quene.getLast().stb);
         } else {
        	 System.out.println("该迷宫无解");
         }
	}
}


/*
方向类
*/
class Direction{
	int inc_x;   //x方向的增量
	int inc_y;   //y方向的增量
	
	public Direction(int inc_x,int inc_y) {
		this.inc_x = inc_x;
		this.inc_y = inc_y;
	}
}

/*
GPS类,成员变量x,y表示坐标,stepNumber表示步数
*/
class GPS{
	int x;
	int y;
	int stepNumber;
	String stb;    //用来记录路径
	
	public GPS(int x,int y,int stepNumber,String stb){
		this.x = x;
		this.y = y;
		this.stepNumber = stepNumber;
		this.stb = stb;
	}
}

以上即是对于BFS和DFS下的迷宫问题的概述。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值