------- 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呢,是将一个节点不断的向四个方向扩展,最终找到目标节点。