原来程序是这样走迷宫的,外行人也能看懂的深度优先搜索思路

一、引出题目

当你遇到程序内容没读不懂并不会影响到解答思路与分析,重点是理解程序是如何走迷宫的思路

题目摘要:给任意指定长度W高度H的迷宫矩阵以及起始点(x,y)终点(x1,y1),要求使用程序遍历所有从起始点(x,y)终点(x1,y1)的所有路线解,并按照路线长度进行排序后打印到屏幕。

  • 输入:
    5 5
    1 1 1 1 1
    1 0 1 1 0
    1 1 1 0 0
    0 0 1 1 1
    1 1 1 0 0
    0 4
    0 0
  • 输出:
    ([(0, 4), (1, 4), (2, 4), (2, 3), (2, 2), (2, 1), (2, 0), (1, 0), (0, 0)], 9)
    ([(0, 4), (1, 4), (2, 4), (2, 3), (2, 2), (1, 2), (0, 2), (0, 1), (0, 0)], 9)
    ([(0, 4), (1, 4), (2, 4), (2, 3), (2, 2), (2, 1), (3, 1), (3, 0), (2, 0), (1, 0), (0, 0)], 11)

二、分析题目

就拿上面题目的输入例子进行分析,第一行输入5 5即生成5×5迷宫矩阵,后面的五行给5×5迷宫矩阵进行通道分布(1可走,0不可走),倒数第二行0 4起始点(0,4),倒数第一行0 0终点(0,0),以上分析后可得出一张矩阵图。

  • 输入:
    5 5
    1 1 1 1 1
    1 0 1 1 0
    1 1 1 0 0
    0 0 1 1 1
    1 1 1 0 0
    0 4
    0 0

在这里插入图片描述

三、思路分析

在做思路分析前,应该对这个迷宫用人脑先走一遍。这个5×5迷宫矩阵甚至三岁的小朋友来说都是心有余且力很足,但程序对于走迷宫这件事情来说,是非常死板的,因为程序永远不知道下一步走的路是死胡同还是终点,有一个名句加以修改后对于程序走迷宫来说特别合适,迷宫就像一盒巧克力,程序永远不知道下一颗是什么味道。

1、人脑路线

在这里插入图片描述
人脑的路线显而易见,只有两条路线行走,并且我相信大部分人的大脑都是遵循以下流程图的思路进行活动的。

Created with Raphaël 2.2.0 大脑开始走迷宫活动 眼睛寻找起始点和终点 是否找到起始点和终点 视起始点为当前格子 记住当前走到的格子 评估起始点到终点的大致方位 找当前格子相邻的下一个最优白格 是否走到终点 大脑结束走迷宫活动 yes no yes no

我们仔细看就会发现,有两个步骤是我们高等动物专有的思维,也就是评估起始点到终点的大致方位找当前格子相邻的下一个最优白格,注意两个关键词评估最优。目前在计算机领域内能实现这两个步骤的也就只能通过人工智能(AI)对模型进行训练,形成一个相对比较成熟的神经网络系统,来完成评估择优的操作。

2、程序路线

既然以上说需要人工智能(AI)才能解出这个走迷宫问题,难道通过非智能就没有办法解决这个问题了吗?有!
我们说程序没办法跟人脑一样可以一边评估一边选一条最优的路线走,那我们就换一个思路,我们把评估起始点到终点大致方位找当前格子相邻的下一个最优白格换成从当前格子上下左右都走一遍,换句话说就是从当前格子开始上下左右的方格都尝试走一下,如果走不通就退回来,从走到当前格子的上一个格子重复尝试,即流程图变成这样。

Created with Raphaël 2.2.0 程序开始走迷宫活动 输入起始点坐标和终点坐标 视起始点为当前格子 记住当前走到的格子 从当前格子往各个方向尝试走 是否走到终点 将走到终点的路线保存下来 是否全部尝试完成 程序结束走迷宫活动 退回上一个找到终点的关键路径 yes no yes no

这么一来,其实就是把5×5矩阵迷宫从起始点到终点的路径全部尝试走一遍,走到终点就把路径保存下来,再退回到上一个路径,继续尝试。以下是程序的步骤图。

注意:我们要把走过的路标记为灰色,让程序知道下一步的路咱们是已经走过了的。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
不难看到现在(上图右侧)已经走到了死胡同,上下都是黑格,往前走就是5×5迷宫矩阵的边界,所以唯一的方法就是回退到上一个路径继续寻找出路。

在这里插入图片描述
当然,回退后的路线(上图左侧)就不能继续再往右边走了,不然就成了一个死循环,只能向上走或者向下走,但是也是被黑色方格堵住了,所以只能继续再回退到上一个路径继续寻找出路。这个时候(上图右侧),只剩下向左走或者向上走,当然合适的路径也只能向上走了。
到目前为止,我们实际上已经实现了深度优先搜索的两次回溯,也就是回退了两次路径,重新回到关键路径上继续尝试。

在这里插入图片描述
在这里插入图片描述
到这里我相信有的小伙伴会质疑,为什么它(上图左侧)往右拐而不是继续向上走,这里就要给你们解释了:这个向上向下向左向右的动作谁优先,是由我们自己程序预先设定的。换句话说,我现在使用优先顺序是这样的:有路的话能先向右就向右走,没路再考虑向上,再没路再考虑向左,最后只能向下,所以这就是为什么他会往右拐

在这里插入图片描述
现在(上图左侧)又遇到了死胡同,于是再进行回溯操作,退回上一个路径,继续尝试向上走或者向左走,由于向上走就出5×5迷宫矩阵上边界了,只能往左边走。

在这里插入图片描述
在这里插入图片描述
到此我们已经把一条路径的解已经找出来了,即在一开始输出例子最长的一条([(0, 4), (1, 4), (2, 4), (2, 3), (2, 2), (2, 1), (3, 1), (3, 0), (2, 0), (1, 0), (0, 0)], 11),大家可以看到程序在做解时所经过的所有坐标,即是我上图分析的步骤记录的。

到目前为止,如果你以上内容认真看完并看得懂,那说明你已掌握了深度优先搜索算法(DFS),英文全称为Depth First Search

总结一下

回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为回溯点

其实迷宫问题是比较能体现回溯法的经典例题之一,因为程序没办法像人的大脑进行实时的评估并择优,程序需要从迷宫内不断地尝试,不断地回溯,这就是程序走迷宫的诀窍。

解决迷宫问题的python程序我已经上传到gitee,欢迎各位大佬前来指正和优化。
《码农小易 - gitee - python算法与解题/迷宫问题》

图文均为原创,如果你觉得文章对你帮助,记得点赞关注一下哦。

猜你喜欢

转载自blog.csdn.net/csdn_xiaoyi/article/details/107667234