利用栈实现迷宫的求解

  问题描述:这时实验心理学中的一个典型的问题,心理学家吧一只老鼠从一个无顶的大盒子的入口处赶进迷宫。迷宫设置很多隔壁,对前进方向形成了许多障碍,心理学家在迷宫的唯一出口处放置了一块奶酪,吸引老鼠仔迷宫中寻找通路以到达出口。

  求解思想:回溯法是一种不断试探且及时纠正错误的搜索方法,下面的求解过程采用回溯法。从入口出发,按某一方向向前探索,若能走通(未走过
的),即某处可以到达,则到达一个新点,否则试探下一个方向;若所有的方向均没有通路,则沿原路返回前一点,换下一个方向继续试探,直到所有可能的通路都
搜索到,或找到一条通路,或无路可走又返回到入口点。这里可以用一个栈来实现,每走一步,将该位置压入栈中,若该点无路可走,则出栈返回上一位置。

  需要解决的四个问题:

  (1)表示迷宫的数据结构

  设迷宫为m行n列,利用数组maze[m][n]来表示一个迷宫,maze[i][j]=0或1,其中0表示通路,1表示不通。迷宫该数组四边都为1,代表迷宫四周都是墙。这样就可以保证每个点都有8个方向可以试探。

  入口为(1,1),出口为(6,8)

1,1,1,1,1,1,1,1,1,1
1,0,1,1,1,0,1,1,1,1
1,1,0,1,0,1,1,1,1,1
1,0,1,0,0,0,0,0,1,1
1,0,1,1,1,0,1,1,1,1
1,1,0,0,1,1,0,0,0,1
1,0,1,1,0,0,1,1,0,1
1,1,1,1,1,1,1,1,1,1

  (2)试探方向

  迷宫中间每个点都有8个方向可以试探。其增量数组可以用一个1*2的二维数组move表述,具体值如下:

x  y

  0  0  1

  1    1     1

  2    1     0

  3    1     -1

  4    0     -1

  5    -1    -1

  6    -1    0

  7    -1    1

  在move数组中,x表示横坐标的增量,y表示纵坐标的增量。

  (3)栈中存放元素的设计

  栈中所存放的元素应该包含所到达的每点的坐标以及从该点沿哪个方向向下走的。可以用一个类表示:

class Step{
    int x,y,d;
    public Step(int x,int y,int d) {
        this.x = x;//横坐标
        this.y = y;//纵坐标
        this.d = d;//方向
    }
}

 (4)防止重复到达某点而发生死循环

  可以用两种方法来实现,第一种就是另外设置一个标志数组mark[m][n],它的所有元素初始都为0,一旦到达某点,则设置该点的标志位1,
下次试探的时候就不再走这点了。第二种就是当到达某点的时候,使maze[i][j]置为-1,以便区别为达到的点,同样也可以防止走重复点的作用。

具体代码如下:

package com.stack;

import java.util.Stack;

/**
 * 用栈来实现迷宫的求解
 * @author 刘玲
 *
 */

class Step{
    int x,y,d;
    public Step(int x,int y,int d) {
        this.x = x;//横坐标
        this.y = y;//纵坐标
        this.d = d;//方向
    }
}

public class MazeTest {

    public static void main(String[] args) {
        // 迷宫定义
        int[][] maze = {{1,1,1,1,1,1,1,1,1,1},
                        {1,0,1,1,1,0,1,1,1,1},
                        {1,1,0,1,0,1,1,1,1,1},
                        {1,0,1,0,0,0,0,0,1,1},
                        {1,0,1,1,1,0,1,1,1,1},
                        {1,1,0,0,1,1,0,0,0,1},
                        {1,0,1,1,0,0,1,1,0,1},
                        {1,1,1,1,1,1,1,1,1,1}};
        int[][] move = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};
        Stack<Step> s = new Stack<Step>();
        Stack<Integer> s1 = new Stack<Integer>();
        int a = path(maze, move, s);
        while(!s.isEmpty()){
            Step step = s.pop();
            System.out.println(step.x+":"+step.y);
        }
    }
    public static int path(int[][] maze,int[][] move,Stack<Step> s){
        Step temp = new Step(1,1,-1); //起点
        s.push(temp);
        while(!s.isEmpty()){
            temp = s.pop();
            int x = temp.x;
            int y = temp.y;
            int d = temp.d+1;
            while(d<8){
                int i = x + move[d][0];
                int j = y + move[d][1];
                if(maze[i][j] == 0){    //该点可达
                    temp = new Step(i,j,d); //到达新点
                    s.push(temp);
                    x = i;
                    y = j;
                    maze[x][y] = -1;  //到达新点,标志已经到达
                    if(x == 6 && y == 8){
                        return 1;  //到达出口,迷宫有路,返回1
                    }else{
                        d = 0;  //重新初始化方向
                    }
                }else{
                    d++; //改变方向
                }
            }
        }
        return 0;
    }

}

输出结果如下:
6:8
5:8
5:7
5:6
4:5
3:5
3:4
3:3
2:2

  由于栈是后进先出的,所以结果应该从下面看起(2,2)->(3,3)->(3,4)->(3,5)->(4,5)->(5,6)->(5,7)->(5,8)->(6,8)

有运行结果可以看出来,栈中所存储的就是迷宫的一条通路。

  上面那个代码有一点点小问题,非常感谢问题的提出者,修改如下:

package com.stack;

import java.util.Stack;

/**
 * 用栈来实现迷宫的求解
 * @author 刘玲
 *
 */

class Step{
    int x,y,d;
    public Step(int x,int y,int d) {
        this.x = x;//横坐标
        this.y = y;//纵坐标
        this.d = d;//方向
    }
}

public class MazeTest {

    public static void main(String[] args) {
        // 迷宫定义
        int[][] maze = {{1,1,1,1,1,1,1,1,1,1},
                        {1,0,1,1,1,0,1,1,1,1},
                        {1,1,0,1,0,1,1,1,1,1},
                        {1,0,1,0,0,0,0,0,1,1},
                        {1,0,1,1,1,0,1,1,1,1},
                        {1,1,0,0,1,1,0,0,0,1},
                        {1,0,1,1,0,0,1,1,0,1},
                        {1,1,1,1,1,1,1,1,1,1}};
        int[][] move = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};
        Stack<Step> s = new Stack<Step>();
        int a = path(maze, move, s);
        while(!s.isEmpty()){
            Step step = s.pop();
            System.out.println(step.x+":"+step.y);
        }
    }
    public static int path(int[][] maze,int[][] move,Stack<Step> s){
        Step temp = new Step(1,1,-1); //起点
        s.push(temp);
        while(!s.isEmpty()){
            //temp = s.pop(); 这样写是有问题的,不能将出栈的元素作为当前位置,应该将栈顶元素作为当前位置
            s.pop();  //如果路走不通就出栈
            if(!s.isEmpty()){
                temp = s.peek();  //将栈顶元素设置为当前位置
            }
            int x = temp.x;
            int y = temp.y;
            int d = temp.d+1;
            while(d<8){
                int i = x + move[d][0];
                int j = y + move[d][1];
                if(maze[i][j] == 0){    //该点可达
                    temp = new Step(i,j,d); //到达新点
                    s.push(temp);
                    x = i;
                    y = j;
                    maze[x][y] = -1;  //到达新点,标志已经到达
                    if(x == 6 && y == 1){
                        return 1;  //到达出口,迷宫有路,返回1
                    }else{
                        d = 0;  //重新初始化方向
                    }
                }else{
                    d++; //改变方向
                }
            }
        }
        return 0;
    }

}
时间: 2024-09-13 23:29:48

利用栈实现迷宫的求解的相关文章

c++-一个利用栈先序线索化二叉树的问题

问题描述 一个利用栈先序线索化二叉树的问题 这是我的代码,我的想法是利用栈在先序遍历的时候把二叉树线索化,可是最后为什么不行呢. 解决方案 不行,是怎么个不行法? 建议你在线索化的过程中,将各个节点的内容打印出来分析,看看线索化的过程是否是按你设计的进行的.

创建单链表并利用栈将其逆置...小白求大神帮改一下多谢。

问题描述 创建单链表并利用栈将其逆置...小白求大神帮改一下多谢. 建立单链表时输入链表数据(字符数据)以'#'号结束. #include #include #define M 20 typedef struct { char data[M]; int top; }SeqStack; typedef struct lnode { char data; struct lnode*next; }LNode,*LinkList; SeqStack*Init_SeqStack() { SeqStack*

Java中栈.回溯.迷宫问题求解

考虑使用一个二维数组表示迷宫.所有的通路用0表示,墙用1表示,出口用9表示,入口用6表 示,已经过点用3表示.输出走出迷宫的过程. 从这个问题的求解过程中可以简单总结出两个算法,一是探路过程,二是输出路线. 1.探路过程 探路过程算法可归纳为: [1]从入口位置开始,检查东西南北四个方向上的通路,如果发现出口则成功退出,否则将所 有通路坐标压入栈; [2]从栈中取出一个坐标,将其标记为当前位置(标记数字3),再次判断通路情况; [3]如此进行,直到发现出口则成功退出,若栈空而且未发现出口,则失败

用栈实现迷宫问题求解

源程序:   //base.h #include  #include  #include  #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define OVERFLOW -2 typedef int Status;   //stack.h #include "base.h" #define INIT_SIZE 100 //存储空间初始分配量 #define INCREMENT 10  //存储空间分配增量 ty

利用栈来实现单链表的逆序

#include <stdio.h># include<stdlib.h>#define stacksize 100typedef int datatype;typedef struct{   datatype data[stacksize];        int  top;}seqstack;typedef struct node{   datatype  data;   struct node *next;}listnode;typedef listnode *linklis

迷宫求解非递归 DFS BFS(应用栈和队列)

栈和队列的应用对迷宫问题求解 没有递归 自己手动建的栈和队 并且输出路径 DFS的路径就是 栈中的坐标 BFS的路径在队又开了一个域存上一层的base值 语言还是用的C++ 感觉比C的封装性好很多 充分体会了一下DFS一边比BFS快 但是BFS是最优解而DFS可能不是最优解   #include <iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace

c++-运用C++栈,链表等基础知识编写一个可运行的迷宫

问题描述 运用C++栈,链表等基础知识编写一个可运行的迷宫 1.1 问题描述:迷宫求解是实验心理学中的一个经典问题.从一个入口处进入迷宫,在迷宫中设置很多的障碍,前进的方向有上.下.左.右,有一个唯一的出口.给出在迷宫中寻找通路到达出口的过程.1.2 基本要求:1.2.1 设计数据结构存储迷宫1.2.2 设计存储结构存储从入口到出口的通路1.2.3 设计算法完成迷宫的求解1.2.4 分析算法的时间复杂度运用C++栈,链表等基础知识编写一个可运行的迷宫,这是数据结构的一知识迷宫图大致为从左上角走到

关于求迷宫最短路径(利用深度优先搜索)的问题

问题描述 关于求迷宫最短路径(利用深度优先搜索)的问题 利用深度优先查找迷宫的最短路径的程序,哪位大神可以帮帮忙吗? 解决方案 迷宫最短路径问题 解决方案二: http://bbs.csdn.net/topics/330218304 解决方案三: http://www.cnblogs.com/GoAhead/archive/2012/09/29/2708673.html

C++利用链栈实现表达式求值_C 语言

本文实例为大家分享了C++利用链栈实现表达式求值的具体代码,供大家参考,具体内容如下 #include<iostream.h> typedef int Status; typedef char Cstack; #define OK 1 #define ERROR 0 typedef struct StackNode { Cstack data; struct StackNode *next; }StackNode,*LinkStack; Status InitStack(LinkStack &