DFS迷宫递归所有路径 新手入门

这篇文章写给自己以后复习和个个入门朋友:提示同学们一定耐心看完解释 哪怕看得很难受,我是新手我懂大家的心烦。看完后慢慢体会代码

 我们假设迷宫为如下状况:
        {0,0,1,0}
        {0,0,1,0}
        {0,0,0,0}
        {0,0,1,0},
 1为墙无法通行 只可以上下左右四个方向走动;目的:从左上角到右下角

DFS深度优先搜索算法思想:这里百度百科有很多 我这里推荐一个http://rapheal.iteye.com/blog/1526863;稍微看一下就好。由于是别人所以尊重原创所以我就不复制了。

那么用DFS解迷宫所有路径:我们在这里采用递归。我们从左上角当成“当前点”开始把出发坐标压入一个栈。每当入栈一个坐标 就把 迷宫所在所标的数值改为-1(当然1也可以,个人这样觉得比较好因为还可以复原迷宫);从左上角开始后从 左上角四个方向(上右下左)开始判断能否走通。比如我们判断当前点上方点的值是否为0;如果是0才可行走。如果上方可以走那么把此点当成当前点。继续判断“当前点”的四个方向,注意上一个当前点不赋值为-1 你就发现那么又要走回去了,因为上一个“当前点”是他左右上下其中的一个嘛。发生死递归等 比如java提示" java.lang.StackOverflowError。可能刚学的不知道什么意思,那么我们就先记住 “防止重复遍历此点”。

那么配图解释:


以上代表一个迷宫,每一格代表每一个通道。

绿色:墙

白色:可以走的路径;

蓝色:上一个当前点(本质是白色方便新手理解);

红色:当前点;(本质是白色)

解释:假如走到红色的地方 此时我们又要判断红色的左右上下可以走否。我们发现红色右是绿色 (墙相当于迷宫的1嘛)。左手边是白色(因为表示上一个当前点所以变成蓝色)所以你将走回去。你走过来走回去干嘛?下面不是还有路吗?所以你要记得把所有走过的节点设置为绿色(设置为1);

最后我们一个个遍历当遇到一个点无法通过时或者找到终点的话返回上一个递归(如果是找到结果,记得先输出逆序栈的坐标,就是其中一个迷宫出路) 返回后记得出栈、并把当前节点设置回0;原因“走不通返回上一个路口嘛。至于为什么重新设置回0的原因比较难阐述 :‘另一个路径又经过这里去寻找终点,却发现这条被走过就放弃从这里出发(其实没走过,是上一个路径走的),在这里有些人有人再想 【你说的和上面那么死递归不是冲突吗?】 其实这里没有冲突:假设我们当前点位B我们上一个当前点为''C(位于C的上方)’、 那么当前点为B ,假设B点除了C方向都是不能通行,而C又是被走过的节点。所以原路返回到到C(出栈一次) 并且B赋值为0; 回到C后我们继续检测其他方向(除了C方向也就是上),这样就不会再去判断上方,因为上下左右只会走一次走过上方发现走不通 就不会在去上了,所以B的值是0又怎么样? ”

代码:

import java.awt.Point;
import java.util.Stack;


public class Main {

	//迷宫我们用二维数组表示,
	//至于为什么边缘都是1,是我加上去的 这样你就可以防止边界越界。
	//慢慢看后面的代码就知道了
	public static int maze[][]={
	   //0 1 2 3 4 5
		{1,1,1,1,1,1},//0
		{1,0,0,1,0,1},//1
		{1,0,0,1,0,1},//2
		{1,0,0,0,0,1},//3
		{1,0,0,1,0,1},//4
		{1,1,1,1,1,1},//5
	};
	//四个方向嘛 上右下左(时针顺序)比如第一个item第一个坐标(-1,0) 
	//我们要计算当前点上面坐标 就加上 item第一个坐标值 
	//假设我们计算(X,Y) 上方坐标 那么就是(X+(-1),Y+0)左右下同理
	static Point item [] ={new Point(-1,0),new Point(0,1),new Point(1,0),new Point(0,-1)};
	//迷宫实际 行数和列数
	static int row=4;
	static int colum=4;
	//用来保存坐标的栈
	static public Stack<Point> stack =new Stack<Point>();
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		DFS(row,colum,new Point(1,1));
		 
	}
	
	//参数信息row colum实际的迷宫总行数和列数 这两个固定的
	//参数信息point当前节点
	public  static void DFS(int row,int colum,Point point){
		//我们到左下角为终点 起点为左上角
		maze[point.x][point.y]=-1;//走过当前节点所以赋值为-1
		stack.add(point);
//		System.out.println("入栈"+point);
		int x,y;
		x= point.x;
		y= point.y;
		//如果是最后结果
		if(row==point.x && colum==point.y){
			printPath();
			//给最后一个节点赋值回0 不然别的路径怎么走得到?
			maze[point.x][point.y]=0;
			
		}else{
			//4个方向分别测试,比如从当前节点向上走不到终点那么返回
			//那么在向右走
			for (int i = 0; i < item.length; i++) {
				Point temp =new Point(x+item[i].x,y+item[i].y);
				if(maze[x+item[i].x][y+item[i].y]==0){
					//如果当前方向可以走,那么进去下一个方向
					DFS(Main.row,Main.colum,temp);
				}
				
			}
		}

		stack.pop();//出栈
		maze[point.x][point.y]=0;
//		System.out.println("出栈"+point);
	}
	//逆序输出栈里面的东西
	public  static void printPath(){
		
		System.out.println("-----------------------");
		for (Point point : Main.stack) {
			System.out.print("["+point.x+","+point.y+"]");
		}
		System.out.println("-----------------------");
	}

}

最后再附上一个非递归版:



posted on 2016-03-09 20:11  木鱼哥  阅读(4400)  评论(0编辑  收藏  举报

导航