当前位置: 首页 > news >正文

算法总结:二维网格 (Grid) DFS 遍历通用模板与实战解析

算法总结:二维网格 (Grid) DFS 遍历通用模板与实战解析

在 LeetCode 中,二维网格(Grid)类型的题目非常常见。这类题目通常要求我们寻找路径、连通块或是检测环。本文将结合 LeetCode 1559. 二维网格图中探测环 和 LeetCode 1391. 检查网格中是否存在有效路径 两道经典题目,为你总结一套通用的 C++ DFS 网格遍历模板。

一、 核心要素拆解

在二维网格中写 DFS,无论题目千变万化,都离不开以下四大核心组件

  1. 方向数组 (DIRS):定义当前格子可以向哪些方向移动。
  2. 访问标记 (vis):记录已经走过的格子,防止死循环或重复计算。
  3. 合法性校验 (Pruning / Validation):判断下一步是否可以走(是否越界、是否满足业务逻辑、是否已访问等)。
  4. DFS 递归主体:进入当前状态 -> 尝试所有分支 -> 校验分支 -> 递归进入下一层。

二、 通用 DFS 模板

结合两道题的精髓(尤其是 C++14+ 及 C++23 引入的this auto&& dfs语法,非常优雅),我们可以提炼出如下通用模板:

C++

classSolution{//1.定义方向数组(根据题目可能固定,也可能动态) static constexprintDIRS[4][2]={{-1,0},{1,0},{0,-1},{0,1}};//上下左右 public:boolsolveGrid(vector<vector<int>>&grid){intm=grid.size(),n=grid[0].size();//2.初始化访问数组 vector vis(m,vector<int8_t>(n,0));//3.定义 DFS 匿名函数 auto dfs=[&](this auto&&dfs,intx,inty,/*可能需要的附加状态,如 px,py*/)->bool{//[可选]终止条件:到达终点等//if(x==targetX&&y==targetY)returntrue;//标记当前节点已访问 vis[x][y]=true;//4.扩展下一个状态for(auto&[dx,dy]:DIRS/*或者 DIRS[grid[x][y]]等动态方向*/){inti=x+dx,j=y+dy;//5.合法性校验:越界检查+业务逻辑检查if(0<=i&&i<m&&0<=j&&j<n){//【分支 A】:如果题目涉及找环,且允许访问已访问过的节点(只要不是上一步的节点)/*if((i!=px||j!=py)&&grid[i][j]==grid[x][y]){if(vis[i][j]||dfs(i,j,x,y))returntrue;}*///【分支 B】:普通的寻路/连通块,只访问未访问的节点/*if(!vis[i][j]&&业务逻辑判断(如管道相连、值相等)){if(dfs(i,j))returntrue;}*/}}returnfalse;};//6.确定搜索起点//场景1:固定起点(如从0,0出发)//returndfs(0,0);//场景2:全图遍历(如找图中任意位置的环/连通块)//for(inti=0;i<m;i++){//for(intj=0;j<n;j++){//if(!vis[i][j]&&dfs(i,j,-1,-1))returntrue;//}//}returnfalse;}};

三、 两道实战题目的差异点总结

虽然使用了同一套骨架,但两道题在具体细节上展示了网格 DFS 的两种常见变体:

1. 方向的控制:固定方向 vs 状态依赖方向

  • LC 1559 (探测环):方向是全局固定的上下左右 4 个方向。我们在当前格子,尝试向四周扩散。
  • LC 1391 (有效路径):方向是由当前格子的状态决定的。管道形状不同,能走的方向也不同。因此方向数组变成了DIRS[street_type],这是一个非常重要的状态转移思想。

2. 避免走回头路的方式:记录父节点 vs 单向管道匹配

  • LC 1559 (探测环):由于是无向图中的环探测,最怕的就是A -> B -> A这种假环。因此 DFS 需要携带(px, py)参数来记录“你是从哪个格子过来的”,在遍历时跳过它 (i != px || j != py)。
  • LC 1391 (有效路径):只要管道能连通,且下一个节点未被访问过 (!vis[i][j]),就可以一直走。不需要记录上一步是谁。

3. 特殊的连通性校验逻辑

  • LC 1391 (有效路径)独有的难点在于,“你能过去,不代表对面能接纳你”。因此多了一个contains函数。从(x, y)(dx, dy)方向走向(i, j),必须保证(i, j)处的管道有一个方向是(-dx, -dy)才能完美对接。

4. 搜索起点的选择

  • LC 1559 (探测环):环可能出现在网格的任何一个角落,且有多个连通块。因此需要在主函数中使用双重for循环遍历每一个未访问的格子作为起点。
  • LC 1391 (有效路径):明确要求从左上角(0, 0)走到右下角,因此属于单源路径搜索,直接dfs(0, 0)即可,不需要双重循环。

四、 结语

掌握了这套模板,以后遇到二维网格的搜索题目,只需按照以下步骤填空:

  1. 确定遍历方向(固定还是动态)。
  2. 确定状态记录(是否需要vis,是否需要记录parent)。
  3. 补全if里的边界和业务规则判定。
  4. 确定如何触发 DFS。

http://www.cnnetsun.cn/news/2140093.html

相关文章:

  • 企业想用AI做数据分析,但数据不能出内网,怎么办
  • M2FP从部署到应用:完整流程解析,快速实现多人图像语义分割
  • 品牌升级后卖不动,先别怪设计公司
  • 虚拟线程CPU爆表却吞吐不升?深度解析Java 25 Project Loom调度器v2.3内核变更,定位3类隐蔽资源饥饿场景
  • 分享一套锋哥原创的微信小程序校园宿舍管理系统(SpringBoot4后端+Vue3管理端)
  • YOLO11涨点优化:卷积魔改 | 引入Dirichlet Convolution (狄利克雷卷积),强化边界特征提取,提升重叠目标识别率
  • 别再为水下AI发愁了!手把手教你用虎鲸开源的UATD声呐数据集(含10类目标、9200张图)
  • Java 25密封类在微服务网关中的真实压测表现:TPS提升23%,错误分类精度达99.8%,附GraalVM原生镜像适配清单
  • 回合策略手游【船长请开炮代金券内购版】服务端搭建教程(含资源下载+部署过程)
  • DeepSeek V4大模型的技术解析与产业实践
  • Unity游戏视觉去马赛克技术解析:6款BepInEx插件实现原理与实战指南
  • CSS三大选择器终极对决!谁才是新手写样式的“最优解”?
  • SQL嵌套查询中常见报错排查_语法与权限处理
  • 别再死记硬背Word2Vec了!用Python+Gensim搞懂CBOW和Skip-gram的区别
  • 企业宣传视频制作:Sonic数字人实战案例,低成本生成专业内容
  • 国风美学生成模型v1.0快速体验:基于CSDN社区案例的模仿生成教程
  • Radxa ROCK E20C迷你网络设备:高性能路由器与轻量级NAS解析
  • 从一次线上故障复盘说起:我是如何用阿里云SLB+ECS+OSS架构,差点搞垮自己网站的
  • 如何在降AI后快速验收效果:多平台交叉验证降AI结果完整操作教程
  • AI时代结构化数据全面普及:谷歌SEO新机遇
  • Arm SVE浮点运算与向量化编程实战指南
  • GHelper完整指南:华硕笔记本终极性能控制工具
  • 为什么90%的Java低代码平台在流程引擎扩展上失败?:深度解析Activity-Driven Runtime内核的3个设计断点
  • 智能清理革命:Pearcleaner为Mac用户打造的终极存储空间解决方案
  • DeepSeek-R1-Distill-Llama-8B部署方案:国产昇腾910B平台适配与性能调优
  • 智能家居能源管理:从基础到优化的全面指南
  • Houdini RBD约束实战:用VEX和锚点属性制作可控制的机械关节动画
  • ARM显示接口与触摸屏控制技术解析
  • 高效VR视频转换方案:5步将3D视频转为普通2D格式的完整指南
  • VMware Workstation Pro 17许可证密钥:5步免费激活终极完整指南