您的位置:首页 > 其它

经典算法(20)给女朋友讲明白 【迷宫问题】

2020-03-06 10:55 375 查看

写在前面: 我是 扬帆向海,这个昵称来源于我的名字以及女朋友的名字。我热爱技术、热爱开源、热爱编程。

技术是开源的、知识是共享的


这博客是对自己学习的一点点总结及记录,如果您对 Java、算法 感兴趣,可以关注我的动态,我们一起学习。

用知识改变命运,让我们的家人过上更好的生活

相关文章

汉诺塔图解及其代码实现

算法系列文章

文章目录

1、问题描述

今天女朋友在刷算法题,委屈巴巴的问我迷宫问题如何解决


先看一下问题的描述

有一个迷宫地图,其中设置了障碍物,四周还有墙壁。只能横着走或竖着走,不能斜着走。从一个位置走到下一个位置只能通过向上(或者向右、或者向下、或者向左)的策略来实现。一个人从起点出发,如何找到一条到达终点的通路?

看完问题描述,我就大概画了一个迷宫图,如下图所示:

迷宫图示

2、实现逻辑

我让她看这个图,然后思考如何实现?

:“用二维数组?”

:“对的!在这个算法中,使用二维矩阵来模拟迷宫地图”

:“迷宫中的通路和墙壁如何表示?”

:“可以使用0和1表示”

:“对,很聪明!

1
代表该位置不能到达(如墙壁或者遮挡物),
0
代表该位置可以到达。”

:“比如小明在迷宫中寻找通路的时候,有没有重复走的情况。如果重复走,如何避免这个情况?”

:“每当走过一个位置就将迷宫地图的对应位置做一个标记,以免重复走,一步步的寻找通路最终到达终点位置。”

到这里,看来她也明白了好多!很开心


:“从每一个位置出发,在走下一步的时候都可以有几种选择?”

:“从每一个位置出发,在走下一步的时候都有四种选择(向上走、向右走、向下走、向左走)。”

然后我就分析了如何走的算法逻辑

  • 先选择一个方向开始走,如果该方向能够走下去,那么就往这个方向开始走,当前位置切换为下一个位置。
  • 如果这个方向不能走,那么换个方向开始走。
  • 如果所有方向都走不通,那么退出当前位置,到上一步的位置去,当前位置切换为上一步的位置。
  • 一直这样执行下去,如果当前位置是终点,那么结束。如果走过了所有的路径都没能到达终点,那么说明这个迷宫走不出来。

:“现在明白没?”

:“明白了!”

:“那你想想如何实现这个算法?”

:使用

递归的方式求解

:“还有其它方式没?

广度优先遍历
深度优先遍历
会不会?”

她:“不会!”

:“嗯嗯,那你就用递归的方式实现吧!首先制定 在迷宫中寻找出路的策略依次是:向上走、向右走、向下走、向左走

接下来就开始写代码吧

3、代码实现

:“你先用二维矩阵画出迷宫地图,包括挡板的位置”

她噼里啪啦一顿操作就写完了

public class Maze {

public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);

int i; // 横坐标
int j; // 纵坐标

// 创建一个10×10的地图
int[][] map = new int[10][10];

// 设置左、右两边为墙,用“1”来代替墙面
for (i = 0; i < 10; i++) {
map[i][0] = 1;
map[i][9] = 1;
}

// 设置上、下两边为墙,用“1”来代替墙面
for (i = 0; i < 10; i++) {
map[0][i] = 1;
map[9][i] = 1;
}

// 设置挡板位置
map[4][1] = 1;
map[4][2] = 1;
map[4][3] = 1;

System.out.println("迷宫地图的情况:");
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
}
}

迷宫地图的情况:

:“现在你可以写个方法,在迷宫地图中寻找通路”

她噼里啪啦一顿操作就写完了,代码如下:

public class Maze {

public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);

int i; // 横坐标
int j; // 纵坐标

// 创建一个10×10的迷宫地图
int[][] map = new int[10][10];

// 设置迷宫地图的左、右两边为墙,用“1”来代替墙面
for (i = 0; i < 10; i++) {
map[i][0] = 1;
map[i][9] = 1;
}

// 设置迷宫地图的上、下两边为墙,用“1”来代替墙面
for (i = 0; i < 10; i++) {
map[0][i] = 1;
map[9][i] = 1;
}

// 设置迷宫地图中的挡板位置
map[4][1] = 1;
map[4][2] = 1;
map[4][3] = 1;

System.out.println("迷宫地图的情况:");
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}

System.out.println("输入小明的起始点 m:");
int m = scanner.nextInt();

System.out.println("输入小明的起始点 n:");
int n = scanner.nextInt();

// 寻找迷宫的出路
mazeTrack(map, m, n);

System.out.println("小明走过,并标识的迷宫地图的情况:");
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
}

/**
* @param maze 表示迷宫地图
* @param i   小明从哪个位置开始找
* @param j   小明从哪个位置开始找
* @return 如果小明找到了通路,就返回true
*/
public static boolean mazeTrack(int[][] maze, int i, int j) {
if (maze[8][8] == 2) { // 如果迷宫中的(8,8)这个点标记为“2”,则说明小明已经找到了出口
return true;
} else {
if (maze[i][j] == 0) { // 当前这个点还没走过
maze[i][j] = 2;
if (mazeTrack(maze, i - 1, j)) { // 探索向上走是否可行
return true;
} else if (mazeTrack(maze, i, j + 1)) { // 探索向右走是否可行
return true;
} else if (mazeTrack(maze, i + 1, j)) { // 探索向下走是否可行
return true;
} else if (mazeTrack(maze, i, j - 1)) { // 探索向左走是否可行
return true;
} else {
// 如果在探索过程中该点走不通,则标记为“3”
maze[i][j] = 3;
return false;
}

} else {
return false;
}
}
}
}

代码执行结果:

看着运行结果,她满脸微笑,看着很开心的样子!O(∩_∩)O哈哈~

:如果改变寻找路的策略,如果在走下一步的时候 按向下、向右、向上、向左这样走,结果会是啥样的。

:那我修改一下代码

public static boolean mazeTrack(int[][] maze, int i, int j) {
if (maze[8][8] == 2) { // 通路已经找到
return true;
} else {
if (maze[i][j] == 0) { // 当前这个点还没走过
maze[i][j] = 2;
if (mazeTrack(maze, i + 1, j)) { // 探索向下走是否可行
return true;
} else if (mazeTrack(maze, i, j + 1)) { // 探索向右走是否可行
return true;
} else if (mazeTrack(maze, i - 1, j)) { // 探索向上走是否可行
return true;
} else if (mazeTrack(maze, i, j - 1)) { // 探索向左走是否可行
return true;
} else {
// 该点走不通,标记为“3”
maze[i][j] = 3;
return false;
}

} else {
return false;
}
}
}

代码执行结果:

:“你看,寻找通路的时候制定的策略不一样,最后走的路也不一样。

这儿涉及到最短路径的问题,等下一次给你再讲

由于水平有限,本博客难免有不足,恳请各位大佬不吝赐教!

  • 点赞 15
  • 收藏
  • 分享
  • 文章举报
扬帆向海 发布了92 篇原创文章 · 获赞 2679 · 访问量 40万+ 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: