回溯法求解迷宫问题
引言
最近在leetcode上看了些算法题,有些看着很简单的很常用的东西,竟然一下子想不出来怎么求解,比如说:实现sqrt函数
,求数组的排列
。如果高数学的不好,这些看似简单的问题,第一次碰到也会感觉很难求解,当然了,今天要说的是这样一个问题,求解迷宫的所有解,这个问题的求解用到了回溯法的思想,不了解这个思想的话,很多稍微复杂点的问题都很难解了。
问题描述
这个问题是在实在瞎逛的时候碰到的,具体哪里记不太清了。
1 1 1 1
0 1 0 1
0 1 0 1
0 1 1 1
上面是一个迷宫,左上角是入口,右下角是出口,小萌(对,你没看错,是长了草的小明)从入口进入,从出口逃出(1个小时逃不出会被X怪物吃掉),其中1表示可以通行,0表示不能通行,只能向右和向下两个方向走,求出所有的小萌可能逃生的路线。
这个问题看似挺简单,一下就可以看到答案,但是将思想翻译为代码却不知道从何入手了。
如何解决
解决这个问题的一种方案就是回溯法,先一起看看回溯法(百度百科)的定义:
回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
我的思路:
- 对上面的迷宫进行坐标化,左上角是(0,0),右下角是(3,3),其他点分散在坐标系中
- 从(0,0)开始
- 从给定的坐标点开始,先向右搜索,是1的话继续,是0的话向下搜索,搜索前记录当前已经搜索过的坐标
- 当坐标等于(3,3)的时候就是一个回溯点了,这个时候也返回
- 只要不越界,重复第三步骤
看看我的PHP实现:
<?php
$nums = [
[1,1,1,1,1,1],
[0,1,0,1,0,1],
[0,1,0,1,0,1],
[0,1,1,1,1,1]
];
function getRet($data, $x, $y, &$result=[], $record)
{
$snapshort = [];
$xL = count($data) - 1;
$yL = count($data[0]) - 1;
if($x > $xL || $y > $yL) {
//跑到迷宫不存在的空间了,这种事情绝对不能发生
return;
}
if($data[$x][$y] == "0") {
//是0的话停止继续前进,退回上一状态
return;
} elseif($data[$x][$y] == "1") {
//是1的话,记录最新的坐标到当前已找到的路径中,继续向前搜索
//如果到达出口,记录答案并回溯
$snapshort = array_merge($record, [[$x, $y]]);
if($x == $xL && $y == $yL) {
$result[] = array_merge($record, [[$x, $y]]);
return;
}
} else {
return;
}
//向有搜索
//这里的$snapshort保存当前搜索位置的状态,等到下次回溯到这里的时候会用到
getRet($data, $x, ++$y, $result, $snapshort);
//向下搜索
getRet($data, ++$x, --$y, $result, $snapshort);
}
//看个例子
$result = [];
getRet($nums, 0, 0, $result, []);
foreach ($result as $pos) {
foreach ($pos as $xy) {
echo "({$xy[0]},{$xy[1]}) => ";
}
echo "end\n";
}
//输出结果
(0,0)=>(0,1)=>(0,2)=>(0,3)=>(0,4)=>(0,5)=>(1,5)=>(2,5)=>(3,5)=>end
(0,0)=>(0,1)=>(0,2)=>(0,3)=>(1,3)=>(2,3)=>(3,3)=>(3,4)=>(3,5)=>end
(0,0)=>(0,1)=>(1,1)=>(2,1)=>(3,1)=>(3,2)=>(3,3)=>(3,4)=>(3,5)=>end
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述