如何用 DFS 正确求解迷宫滚动球的最短路径问题

酷强小哥_3868

酷强小哥_3868

2026-06-30

192人浏览

原创

本文详解为何朴素 dfs 无法保证找到 maze ii 类滚动球问题的最短路径,并给出两种关键改进方案:基于方向状态的 visited 三维标记与带距离剪枝的动态更新机制。

本文详解为何朴素 dfs 无法保证找到 maze ii 类滚动球问题的最短路径,并给出两种关键改进方案:基于方向状态的 visited 三维标记与带距离剪枝的动态更新机制。

在图论与算法实践中,DFS(深度优先搜索)常被误用于求解“最短路径”问题——尤其在 LeetCode 的 Maze II 这类滚动球迷宫题中。题目要求球从起点出发,沿上下左右四个方向持续滚动直至撞墙停止,每次停驻点构成一个有效状态;目标是找到抵达终点的最小滚动步数(即经过的空格总数)。虽然 BFS 天然适配无权图最短路径,但许多开发者尝试用 DFS 实现,却屡次得到错误结果(如示例输入应输出 12,而原始代码返回 16)。根本原因在于:标准 DFS 缺乏对“同一位置不同进入方向”状态的区分能力,且未对非最优路径进行及时剪枝。

❌ 原始 DFS 的致命缺陷

原始实现使用二维 visited[i][j] 标记已访问坐标,一旦某坐标 (i, j) 被访问过,后续任何方向滚入该点都会被跳过。然而,在滚动模型中,从不同方向到达同一坐标,代表完全不同的状态——因为下一步可选的滚动方向受当前“来向”影响(例如,从上方滚入后不能立即向上反向滚动,但可向左/右/下继续),更重要的是:更晚到达某点的路径,可能对应更小的累计距离。二维 visited 粗暴阻断了所有后续可能性,导致更优路径被提前扼杀。

此外,原始代码在进入递归前未做任何距离判断,即使当前 count 已远超已知最优解,仍继续深搜,造成大量无效计算。

✅ 改进方案一:三维 visited —— 按“到达方向”精细化状态

关键洞察:每个停驻点 (x, y) 需记录 以哪个方向(0: 上,1: 下,2: 左,3: 右)滚入 时的访问状态。因此将 visited 升级为三维布尔数组 visited[x][y][dirIdx]:

小旺AI截图
小旺AI截图

一款AI图像与设计工具,主要用于首款接入DeepSeek的AI截图神器!轻巧、好用、免费、无广告!,适合需要提升相关任务效率的用户。

下载
boolean[][][] visited = new boolean[maze.length][maze[0].length][4];
// 在 dfs 中检查并标记
if (!visited[x][y][k]) {
    visited[x][y][k] = true;
    dfs(maze, x, y, destination, visited, newcount);
    visited[x][y][k] = false; // 回溯(若需复用状态)
}

此设计确保:(2,3) 点从上方滚入(dirIdx=0)和从左侧滚入(dirIdx=2)被视为两个独立状态,互不干扰。这解决了状态覆盖问题,使 DFS 能探索所有合法路径分支。

✅ 改进方案二:距离驱动剪枝 —— 动态更新最优到达代价

更进一步,我们不仅需要知道“是否来过”,更要记录“以某方向到达 (x,y) 的最小步数”。于是将 visited 替换为 dist[x][y][dirIdx],初始化为 Integer.MAX_VALUE:

int[][][] dist = new int[maze.length][maze[0].length][4];
for (int i = 0; i <p>该策略实现了 <strong>Dijkstra 式的距离松弛</strong>:仅当发现更短路径到达 (x,y) 的某个方向状态时,才继续递归。这大幅减少搜索空间,避免陷入长路径陷阱,是 DFS 求解最短路的核心优化。</p><h3>⚠️ 注意事项与总结</h3>
  • DFS ≠ 最短路径算法:除非辅以状态去重与距离剪枝,否则 DFS 仅保证可达性,不保证最优性。
  • 状态定义决定正确性:滚动球问题的状态必须包含 (行, 列, 入口方向) 三元组,缺一不可。
  • 剪枝优于回溯:在递归入口处用 if (newcount >= dist[x][y][k]) return; 直接剪枝,比回溯标记更高效。
  • 实际推荐方案:尽管改进后 DFS 可行,但 Maze II 的本质是边权为正的无向图最短路径问题,优先选用 Dijkstra(堆优化)或 BFS(因边权恒为1,但注意:此处“边权”是滚动距离,非单位步,故严格需 Dijkstra)。DFS 改进版更多用于理解状态建模思想。

最终,正确实现的 DFS 不再是盲目遍历,而是以状态空间建模为基石、以距离优化为引擎的精确搜索——这正是图算法从“能跑通”迈向“可证明正确”的关键跃迁。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
FrankenPHP集成Laravel详细教程
FrankenPHP集成Laravel详细教程

本专题提供FrankenPHP集成Laravel的详细配置指南,全面解析运行原理、开发环境搭建、Caddyfile配置、Octane工作模式、数据库连接、队列任务、定时任务和生产环境优化,解决部署过程中常见的报错与兼容性问题。

2026.10.08

40

20

LLVM自定义Pass怎么写
LLVM自定义Pass怎么写

本专题聚焦LLVM自定义Pass开发,整理Pass类结构、run()方法、PreservedAnalyses、CMake构建、插件注册、-load-pass-plugin加载和测试用例编写流程。

2026.09.30

140

10

LLVM RISC-V参数配置教程
LLVM RISC-V参数配置教程

本专题介绍LLVM对RISC-V基础ISA和扩展的支持方式,涵盖RV32、RV64、标准扩展、实验性扩展、厂商扩展、-menable-experimental-extensions和版本差异。

2026.09.30

140

14

LLVM IR中间表示入门指南
LLVM IR中间表示入门指南

本专题整理LLVM IR的核心概念,包括中间表示作用、模块结构、函数、基本块、SSA形式、类型系统和常见语法,帮助新手理解LLVM编译流程中的关键层。

2026.09.30

100

12

PDF转图片方法
PDF转图片方法

需要把 PDF 页面用于上传、预览、分享或图片归档时,PDF 转图片方法专题整理 JPG/PNG 格式选择、逐页导出、清晰度设置、批量下载和结果检查等流程,帮助用户稳定完成 PDF 图片化处理。

2026.09.30

100

26

PixTV AI视频生成与无限画布创作
PixTV AI视频生成与无限画布创作

PixTV专题整理AI视频与视觉内容创作相关功能使用教程,涵盖AI生图、视频生成、无限画布、多模型创作、素材管理、声音音乐及视频剪辑等功能,帮助用户快速掌握PixTV从创意到成片的完整制作方法。

2026.09.29

120

15

Buffalo框架数据库开发全教程
Buffalo框架数据库开发全教程

本专题围绕Buffalo框架数据库开发,讲解database.yml多环境配置、soda与fizz迁移生成回滚、模型结构体标签、增删改查与条件查询、一对多与多对多关联、数据校验、回调钩子、事务处理及原生SQL执行能力。

2026.09.23

320

15

Buffalo框架路由与请求处理实操指南
Buffalo框架路由与请求处理实操指南

本专题讲解Buffalo框架路由与请求处理机制,涵盖路由注册与分组、资源路由、Handler编写规范、Context上下文方法、参数绑定、中间件编写挂载、Session与Cookie读写、Flash消息及错误页面定制方法。

2026.09.23

220

15

Buffalo框架零基础入门教程
Buffalo框架零基础入门教程

本专题整理Buffalo框架入门内容,涵盖Go环境准备、buffalo CLI安装、新项目生成、目录结构说明、dev热加载启动、数据库连接配置与常见报错排查,帮助新手按约定优于配置的思路跑通第一个Buffalo框架应用。

2026.09.23

180

15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.6万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.4万人学习