打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
利用栈实现迷宫的求解

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

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

  需要解决的四个问题:

  (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)栈中存放元素的设计

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


1 class Step{2     int x,y,d;3     public Step(int x,int y,int d) {4         this.x = x;//横坐标5         this.y = y;//纵坐标6         this.d = d;//方向7     }8 }

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

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

具体代码如下:


 1 package com.stack; 2  3 import java.util.Stack; 4  5 /** 6  * 用栈来实现迷宫的求解 7  * @author 刘玲 8  * 9  */10 11 class Step{12     int x,y,d;13     public Step(int x,int y,int d) {14         this.x = x;//横坐标15         this.y = y;//纵坐标16         this.d = d;//方向17     }18 }19 20 public class MazeTest {21 22     public static void main(String[] args) {23         // 迷宫定义24         int[][] maze = {{1,1,1,1,1,1,1,1,1,1},25                         {1,0,1,1,1,0,1,1,1,1},26                         {1,1,0,1,0,1,1,1,1,1},27                         {1,0,1,0,0,0,0,0,1,1},28                         {1,0,1,1,1,0,1,1,1,1},29                         {1,1,0,0,1,1,0,0,0,1},30                         {1,0,1,1,0,0,1,1,0,1},31                         {1,1,1,1,1,1,1,1,1,1}};32         int[][] move = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};33         Stack<Step> s = new Stack<Step>();34         Stack<Integer> s1 = new Stack<Integer>();35         int a = path(maze, move, s);36         while(!s.isEmpty()){37             Step step = s.pop();38             System.out.println(step.x ":" step.y);39         }40     }41     public static int path(int[][] maze,int[][] move,Stack<Step> s){42         Step temp = new Step(1,1,-1); //起点43         s.push(temp);44         while(!s.isEmpty()){45             temp = s.pop();46             int x = temp.x;47             int y = temp.y;48             int d = temp.d 1;49             while(d<8){50                 int i = x   move[d][0];51                 int j = y   move[d][1];52                 if(maze[i][j] == 0){    //该点可达53                     temp = new Step(i,j,d); //到达新点54                     s.push(temp);55                     x = i;56                     y = j;57                     maze[x][y] = -1;  //到达新点,标志已经到达58                     if(x == 6 && y == 8){59                         return 1;  //到达出口,迷宫有路,返回160                     }else{61                         d = 0;  //重新初始化方向62                     }63                 }else{64                     d  ; //改变方向65                 }66             }67         }68         return 0;69     }70 71 }

输出结果如下:
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)

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

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


 1 package com.stack; 2  3 import java.util.Stack; 4  5 /** 6  * 用栈来实现迷宫的求解 7  * @author 刘玲 8  * 9  */10 11 class Step{12     int x,y,d;13     public Step(int x,int y,int d) {14         this.x = x;//横坐标15         this.y = y;//纵坐标16         this.d = d;//方向17     }18 }19 20 public class MazeTest {21 22     public static void main(String[] args) {23         // 迷宫定义24         int[][] maze = {{1,1,1,1,1,1,1,1,1,1},25                         {1,0,1,1,1,0,1,1,1,1},26                         {1,1,0,1,0,1,1,1,1,1},27                         {1,0,1,0,0,0,0,0,1,1},28                         {1,0,1,1,1,0,1,1,1,1},29                         {1,1,0,0,1,1,0,0,0,1},30                         {1,0,1,1,0,0,1,1,0,1},31                         {1,1,1,1,1,1,1,1,1,1}};32         int[][] move = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};33         Stack<Step> s = new Stack<Step>();34         int a = path(maze, move, s);35         while(!s.isEmpty()){36             Step step = s.pop();37             System.out.println(step.x ":" step.y);38         }39     }40     public static int path(int[][] maze,int[][] move,Stack<Step> s){41         Step temp = new Step(1,1,-1); //起点42         s.push(temp);43         while(!s.isEmpty()){44             //temp = s.pop(); 这样写是有问题的,不能将出栈的元素作为当前位置,应该将栈顶元素作为当前位置45             s.pop();  //如果路走不通就出栈46             if(!s.isEmpty()){47                 temp = s.peek();  //将栈顶元素设置为当前位置48             }49             int x = temp.x;50             int y = temp.y;51             int d = temp.d 1;52             while(d<8){53                 int i = x   move[d][0];54                 int j = y   move[d][1];55                 if(maze[i][j] == 0){    //该点可达56                     temp = new Step(i,j,d); //到达新点57                     s.push(temp);58                     x = i;59                     y = j;60                     maze[x][y] = -1;  //到达新点,标志已经到达61                     if(x == 6 && y == 1){62                         return 1;  //到达出口,迷宫有路,返回163                     }else{64                         d = 0;  //重新初始化方向65                     }66                 }else{67                     d  ; //改变方向68                 }69             }70         }71         return 0;72     }73 74 }

 


 

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
栈的妙用-实现迷宫问题(转)
常用算法四(回溯算法)
纯c语言迷宫源码
DFS解迷宫(输出路径)hdoj1010
每日一题 C++版(走迷宫)
董乘宇--迷宫程序
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服