首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

C+不知算法系列之迷宫问题中的“见山不是山”

1. 前言

迷宫问题是一类常见的问题。

初识此类问题,应该是“见山是山”,查询从起点到终点的可行之路。

有了广泛的知识体系之后,应该是"见山不是山"。会发现迷宫就是邻接矩阵,树和图中顶点的关系常用邻接矩阵描述,所以,迷宫问题可以转化为树、图的搜索问题。

最后便是“见山还是山”,能透过问题的表象,深化问题的本质,识破披着各色外衣的迷宫问题。

本文从不同的角度、全方位讲透迷宫问题中的“见山不是山”,让大家对迷宫问题有实质性的理解。

2. 迷宫问题

问题描述:

如下图迷宫地图中,表示障碍物,表示可通行。要求从起始点出发,检查是否有行之有效的通路,可以一直走到终点。迷宫问题的本质就是邻接矩阵的路径搜索问题。

常用的是和搜索算法。

2.1 设计数据结构

首先分析中的数据类型。

坐标类型:用来描述迷宫中每个单元格的位置。

方向类型:描述与每个单元格相邻的上、下、左、右 个单元格的关系。

迷宫类:描述本身以及迷宫相对应的操作函数。

2.2 检查连通性

使用检查迷宫的连通性。

洪水填充算法类似于古时候的"连坐法",或说星星之火可以燎原也,从最初给定的位置开始,以蔓延之势,用填充与之相邻且值为 的单元格。本文中, 和都用于表示迷宫中的非障碍物区间。

洪水填充算法和后面的递归搜索算法相似,不同地方之处,会蔓延至所有满足条件的位置,搜索则是强调到通向目标的路径。

连通性结论:

测试:

输出结果: 迷宫中值为的位置全部被填充。

2.3 深度搜索

深度搜索可以使用非递归和递归 种方案实现。

2.3.1  非递归的思想

非递归深度搜索需要借助栈。

初始,把的坐标值压入栈中。

获取栈顶的坐标,检查此坐标的  个相邻的坐标是否可通行。如果可通行,则压入栈中,且标识此坐标已经访问过。如下图使用绿色表示已经访问过。

重复上述的的逻辑,如下图当是添加到单元格时栈中的内容。

与相邻的坐标分别是。其中已经访问过,则不需要再压入。栈中的坐标都是一路搜索下来可通行的位置。

继续获取栈顶坐标。随后找到与之相邻的,压入栈中;再得到栈顶的坐标,并找到与之相邻的。

Tips: 本文查找与栈顶坐标相邻的坐标是按的顺序。如果顺序不同,则会导致搜索过程不一样。

从栈顶得到,因此坐标位于。于是,从栈顶把此坐标删除。可得到一个结论,不是所有进入栈中的坐标都有机会成为有效路径中的一份子。本文称行之此处不能通行的坐标为坐标,也做相应的标记。也就是说,当坐标为坐标时,则从栈顶删除。

栈中的为坐标,删除。

从坐标开始,可以一路走到终点。把栈中的坐标全部输出便得到到的有效路径。

这里有一个问题要思考,栈中的值真的全是有效路径上的坐标?

其实不然,也许有些坐标进入栈中,只为备用。如到位置时,有 个可行方向。因这个方向可行,最终备用点没用上。所以,这些坐标也需要标记一下,本文称为。

对坐标进行不同颜色标记后,上图中的绿色坐标为最终有效路径。

2.3.2 编码实现

测试:

输出结果: 下图中的所示的坐标为有效路径描述。曾经进入过栈,但是死胡同坐标。 表示没有用上的备用坐标。

2.4 递归实现

可以使用,找出所有的路径。

测试代码:

注释如下代码:

会显示一条路径。如下图所示,表示递归过,但是的坐标。标记为大于等于 的位置为可正常通行。

如果打开如下代码。

显示所有路径,回溯不用判断死胡同坐标,回溯时会自动恢复原来的状态。

2.4 广度搜索

在家拖地时,如果从当前位置向前拖,然后再折回,这和深度优先搜索方式一样。另一种是从左向右方式,逐渐向远处外延,这和广度搜索一样。

广度优先类似于一石激起千层浪,一层层向外推动。

输出结果: 迷宫中的广度优先搜索相当于在无向图中查找路径,可以找到任何 个可通行位置的最短路径。这里只显示起点到终点的最短路径,如下所标记的坐标连接起来的路径。

3. 总结

迷宫本质是邻接矩阵,可用来存储树和图的关系。所以,迷宫问题可归结于树或图的路径搜索问题。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20230103A06W6C00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券