黑马程序员----经典问题(走迷宫)

本文介绍了一种求解迷宫最短路径的经典算法。利用递归和广度优先搜索(BFS)两种方法,实现从起点到终点的最短步数计算。通过栈记录路径并回溯,确保所有可能路径都被探索。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

------- android培训java培训、期待与您交流! ----------

迷宫问题

描述

求迷宫中从入口到出口的所有路径是一个经典的程序设计问题。由于计算机解迷宫时,通常用的是“穷举求解”的方法,即从入口出发,顺着某一个方向向前探索,若能走通,则继续往前走;否则沿着原路退回,换一个方向再继续探索,直至所有可能的通路都探索到为止。为了保证在任何位置都能沿原路退回,显然需要用一个栈来保存从入口到当前位置的路径。因此,这样的题目可以用栈来解决,当然也可以用类似的方法完成求解。

如一个典型的问题是:迷宫求最短路径。只能走上、下,左、右四个方向。

输入

输入只有一个用例。

第一行为迷宫大小,n,m,即n行m列,

第二行为起点位置,

第三行为终点位置,

接下来的为迷宫图,1表示墙壁,0表示通道

输出

输出从起点到终点的最短路径,即最少走的步数。

样例输入

10 10
2 2
9 9
1 1 1 1 1 1 1 1 1 1
1 0 0 1 0 0 0 1 0 1
1 0 0 1 0 0 0 1 0 1
1 0 0 0 0 1 1 0 0 1
1 0 1 1 1 0 0 0 0 1
1 0 0 0 1 0 0 0 0 1
1 0 1 0 0 0 1 0 0 1
1 0 1 1 1 0 1 1 0 1
1 1 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1

样例输出

14

首先我们用递归求解

import java.util.Scanner;
public class Main {
	//用来保存在递归过程中所走的路径,如果为true表示走过,
public static boolean flag[][] = new boolean[20][20];
	//用来表示地图
	public static int maze[][] = new int[20][20];
	public static int n ,m, endx, endy, startx, starty;
	//用来保存所有路径中的最小值
	public static int minx ;
	public static void main(String[] args) {
		
		Scanner sca = new Scanner( System.in );				while( sca.hasNext() )		{
			n = sca.nextInt(); //输入地图范围
			m = sca.nextInt();
			startx = sca.nextInt();//开始位置
			starty = sca.nextInt();
			endx = sca.nextInt();//结束位置
			endy = sca.nextInt();
			minx = 10000000;//初始值为最大值
			for( int i = 1; i <= n; i++ )
			for( int j = 1; j <= m; j++ )	{
				flag[i][j] = false;
				maze[i][j] = sca.nextInt();
			}
			Find_path( startx, starty, 0 );//递归查找
			System.out.println( minx );
		}
	}	
	//枚举四个方向
	public static int dir[] = { 0, 1, 0, -1, 0 };
	public static void Find_path( int x, int y, int step ) {
		
		if( x == endx && y == endy ) {	//如果等于重点,则比较最小步数		
			if( step < minx ) minx = step;
			return ;			
		}		
		//这里是一个小的优化,如果当前走的步数已经大于了最小步数,那么直接返回,这条路不用走下去
		if( step > minx ) return ;		
		for( int i = 0; i < 4; i++ ) {
			//这里的四个方向分别是 (0,1),(1,0),(0,-1),(-1,0)
			int xx = dir[i] + x;
			int yy = dir[i+1] + y;
			//判断当前所走的地方是否越界,或者是否被走过,或者是墙壁不能走
			if( xx >= 1 && xx <= n && yy >= 1 && yy <= m  && !flag[xx][yy] && maze[xx][yy]==0 )
			{
				flag[xx][yy] = true;//把当前位置标记为true , 走过
				Find_path(xx, yy, step+1);//从当前位置进行递归
				flag[xx][yy] = false;//退回的时候标记还没走过
			}			
		}		
	}	
}


图画的不是很好,但至少能表现出递归的路线


下面是用队列写的,俗称BFS

package com.itheima;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class Main {
	//用来保存在递归过程中所走的路径,如果为true表示走过,
	public static boolean flag[][] = new boolean[20][20];
	//用来表示地图
	public static int maze[][] = new int[20][20];
	public static int n ,m, endx, endy, startx, starty;
	//用来保存所有路径中的最小值
	public static int minx;

	public static void main(String[] args) {
		
		Scanner sca = new Scanner( System.in );		
		while( sca.hasNext() )
		{
			n = sca.nextInt(); //输入地图范围
			m = sca.nextInt();
			startx = sca.nextInt();//开始位置
			starty = sca.nextInt();
			endx = sca.nextInt();//结束位置
			endy = sca.nextInt();
			minx = 10000000;//初始值为最大值
			for( int i = 1; i <= n; i++ )
			for( int j = 1; j <= m; j++ )	{
				flag[i][j] = false;
				maze[i][j] = sca.nextInt();
			}
			Find_path( startx, starty );//递归查找
			System.out.println( minx );
		}
	}
	
	//枚举四个方向
	public static int dir[] = { 0, 1, 0, -1, 0 };
	
	public static void Find_path( int x, int y ) {
		
		Queue<Node> queue = new LinkedList<Node>();
		queue.add( new Node( x,y,0 ) );
		flag[x][y] = true;
		while( !queue.isEmpty() )
		{
			Node a = queue.poll(); //出队列,找一个点进行四个方向枚举
			if( a.x == endx && a.y == endy ) {
				//找到终点位置
				minx = a.step;
				break;
			}
		
			for( int i = 0; i < 4; i++ ) {
				int xx = a.x + dir[i];
				int yy = a.y + dir[i+1];
				if( xx >= 1 && xx <= n && yy >= 1 && yy <= m  && !flag[xx][yy] && maze[xx][yy]==0 )
				{
					flag[xx][yy] = true;//把当前位置标记为true , 走过
					//进队列
					queue.add( new Node(xx, yy, a.step+1) );
				}
			}
		}
	}	
}

class Node {
	public Node( int x, int y, int step ) {
		this.x = x;
		this.y = y;
		this.step = step;
	}
	public Node() {}
	int x, y, step;
}


这BFS呢,是将一个节点不断的向四个方向扩展,最终找到目标节点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值