首页/新闻资讯/正文详情

Dijkstra算法与动态规划在图论问题中的协同应用

发布时间:2026/11/2 19:24:59 来源:云帆数科 栏目:资讯中心
Dijkstra算法与动态规划在图论问题中的协同应用
1. 题目背景与核心挑战LeetCode 2977题是一道结合了Dijkstra算法和动态规划(DP)的图论问题这类题型在周赛和面试中频繁出现。题目通常会给出一张带权有向图要求计算从起点到终点的某种最优路径而约束条件往往需要通过DP状态设计来解决。这道题的难点在于识别出何时该用Dijkstra处理路径权重何时该用DP处理状态转移。许多参赛者在初次遇到时会陷入两个误区要么试图纯用Dijkstra暴力求解导致超时要么DP状态设计不当遗漏关键约束。我在第一次尝试时也花了近40分钟才理清思路后来通过系统总结发现了这类问题的通用解法模式。2. Dijkstra算法的适用场景与优化2.1 为什么选择Dijkstra而非其他最短路径算法当题目中出现最短路径、最小代价等关键词且边权为非负数时Dijkstra就是首选方案。相比Floyd-Warshall的O(n³)复杂度Dijkstra的O(E VlogV)复杂度更适合处理稀疏图。以LeetCode 743题为例def networkDelayTime(times, n, k): graph defaultdict(list) for u, v, w in times: graph[u].append((v, w)) heap [(0, k)] dist {node: float(inf) for node in range(1, n1)} dist[k] 0 while heap: current_dist, u heapq.heappop(heap) if current_dist dist[u]: continue for v, w in graph[u]: if dist[v] dist[u] w: dist[v] dist[u] w heapq.heappush(heap, (dist[v], v)) max_dist max(dist.values()) return max_dist if max_dist float(inf) else -12.2 堆优化实现的关键细节使用最小堆优化时要注意三个易错点每次从堆中取出的距离可能已不是最新值需要通过if current_dist dist[u]: continue过滤过期数据邻接表的存储方式比邻接矩阵更节省空间适合处理稀疏图Python的heapq模块默认是最小堆若要最大堆需要存储负值提示在竞赛环境中建议预先生成完整的邻接表结构避免在松弛操作中频繁进行哈希查找影响性能。3. 动态规划的状态设计与转移3.1 识别DP适用条件当问题具有以下特征时需要考虑DP求最优解最大/最小值存在重叠子问题具有最优子结构性质在2977题中除了基本的最短路径要求外通常还会有额外约束如必须经过特定节点路径长度限制多维度代价计算3.2 经典状态设计模式对于图上的DP常用状态定义为dp[u][state]表示到达节点u且处于state状态时的最优解。例如# 伪代码示例 dp [[float(inf)] * (1 k) for _ in range(n)] dp[start][0] 0 for state in range(1 k): for u in nodes: if dp[u][state] float(inf): continue for v, weight in graph[u]: new_state state | (1 must_pass[v]) if dp[v][new_state] dp[u][state] weight: dp[v][new_state] dp[u][state] weight4. Dijkstra与DP的协同工作模式4.1 分层图思想将DP状态融入图的节点中构建分层图每个原始节点拆分为多个状态节点边转移同时考虑路径权重和状态变化使用Dijkstra在分层图上求最短路4.2 实现模板def solve(): # 初始化 heap [(0, start_state)] dist defaultdict(lambda: float(inf)) dist[start_state] 0 while heap: current_dist, state heapq.heappop(heap) if current_dist dist[state]: continue # 状态转移 for next_state, cost in get_neighbors(state): if dist[next_state] dist[state] cost: dist[next_state] dist[state] cost heapq.heappush(heap, (dist[next_state], next_state)) return dist[target_state]5. 实战案例分析5.1 LeetCode 1976. 到达目的地的方案数这道题完美展示了DijkstraDP的组合应用先用Dijkstra求出所有节点到终点的最短距离定义dp[u]为从u到终点的最短路径数目按照到终点的距离升序处理节点保证DP的无后效性def countPaths(n, roads): graph defaultdict(list) for u, v, time in roads: graph[u].append((v, time)) graph[v].append((u, time)) # Dijkstra求最短路 dist [float(inf)] * n dist[0] 0 heap [(0, 0)] while heap: d, u heapq.heappop(heap) if d dist[u]: continue for v, time in graph[u]: if dist[v] dist[u] time: dist[v] dist[u] time heapq.heappush(heap, (dist[v], v)) # DP过程 nodes sorted(range(n), keylambda x: dist[x]) dp [0] * n dp[0] 1 for u in nodes: for v, time in graph[u]: if dist[v] dist[u] time: dp[v] (dp[v] dp[u]) % (10**9 7) return dp[-1]5.2 调试技巧与边界处理在实现这类算法时我总结了几条实用技巧打印中间状态在Dijkstra和DP的关键步骤后输出dist和dp数组小规模测试先用手算能验证的小图测试特殊用例单节点图不连通图存在重边的图最大规模极限测试6. 性能优化与进阶技巧6.1 双向Dijkstra的应用当图规模较大时可以考虑从起点和终点同时进行Dijkstra搜索def bidirectional_dijkstra(graph, start, end): # 前向搜索 dist_start {start: 0} heap_start [(0, start)] # 后向搜索 dist_end {end: 0} heap_end [(0, end)] visited_start set() visited_end set() while heap_start and heap_end: # 前向步 d1, u heapq.heappop(heap_start) if u in visited_start: continue visited_start.add(u) # 相遇检查 if u in visited_end: return dist_start[u] dist_end[u] # 后向步 d2, v heapq.heappop(heap_end) if v in visited_end: continue visited_end.add(v) # 相遇检查 if v in visited_start: return dist_start[v] dist_end[v] # 松弛操作略6.2 A*搜索的启发式函数当图具有空间特性时A*算法可能更高效def heuristic(node, target): # 实现合适的启发式函数如曼哈顿距离 return abs(node.x - target.x) abs(node.y - target.y) def a_star(graph, start, end): heap [(0 heuristic(start, end), 0, start)] dist {start: 0} while heap: _, current_dist, u heapq.heappop(heap) if u end: return current_dist for v, weight in graph[u]: if v not in dist or current_dist weight dist[v]: dist[v] current_dist weight heapq.heappush(heap, (dist[v] heuristic(v, end), dist[v], v)) return -17. 常见错误与验证方法7.1 Dijkstra实现中的陷阱未处理重复节点同一个节点可能被多次加入堆中错误终止条件应在找到目标节点时立即返回但有时需要处理所有节点负权边处理Dijkstra不能处理含负权边的图验证方法手动计算小图的最短路径检查是否满足三角不等式dist[v] ≤ dist[u] weight(u,v)7.2 DP状态转移错误典型错误包括状态转移顺序不当未正确处理边界条件状态压缩时位运算错误调试建议打印每个状态的转移过程使用assert检查不变式对比暴力解法的结果8. 扩展应用与变种问题8.1 多目标优化问题当需要同时优化多个指标时如时间和费用可以将状态扩展为多维dp [[float(inf)] * (max_cost 1) for _ in range(n)] dp[start][0] 0 for cost in range(max_cost 1): for u in range(n): if dp[u][cost] float(inf): continue for v, (time, edge_cost) in graph[u]: new_cost cost edge_cost if new_cost max_cost: if dp[v][new_cost] dp[u][cost] time: dp[v][new_cost] dp[u][cost] time8.2 随机图上的期望最短路径当边权具有概率特性时可以结合期望计算# E[u] Σ (p_uv * (w_uv E[v])) def expected_shortest_path(graph, start, end): E {node: 0 if node end else float(inf) for node in graph} for _ in range(len(graph) - 1): for u in graph: if u end: continue total 0 for (v, w, p) in graph[u]: total p * (w E[v]) E[u] total return E[start]在实际刷题过程中我发现这类问题的解题能力会随着刻意练习快速提升。建议从LeetCode 743、787、1976等题开始逐步过渡到周赛的hard题目。每次AC后记录下自己的解题思路和优化点形成个人解题模板库。

相关推荐

MCP协议:AI工具调用的标准化与动态扩展
MCP协议:AI工具调用的标准化与动态扩展

1. AI工具调用技术的演进背景在AI技术快速发展的当下,大模型与外部工具的交互能力已成为决定其实际应用价值的关键因素。早期的AI系统主要依靠预训练的知识库进行问答,但随着应用场景的复杂化,这种"闭卷考试"模式逐渐暴露出两大核心… · 2026/11/2 19:24:59

HTML转PDF实战:渲染引擎选型、分页控制与质量验证全解析
HTML转PDF实战:渲染引擎选型、分页控制与质量验证全解析

简介:面向.NET开发者与Web文档处理场景的HTML转PDF实战示例包,围绕Aspose.Pdf库演示如何将HTML字符串或网页内容稳定转换为保留原始布局的PDF文档。压缩包共32个文件、约10.62MB,以8个PDF参考文档、4个C#源码文件、3个DLL程序集及配套config配… · 2026/11/2 19:24:59

便携浏览器做网侦渗透:环境隔离与可复现测试环境搭建指南
便携浏览器做网侦渗透:环境隔离与可复现测试环境搭建指南

简介:神行-网侦(渗透)便携浏览器面向网络安全从业者、渗透测试人员及IT管理员,提供一套免安装、可随U盘或移动设备快速部署的便携式安全检测环境,用于网络侦查、漏洞扫描与安全评估等合法测试场景。压缩包为rar格式,整体约120.62M… · 2026/11/2 19:24:59

从零学AI工程:数据、部署、监控的避坑指南与实战路线
从零学AI工程:数据、部署、监控的避坑指南与实战路线

从零开始学AI工程:我踩过的坑,和真正值得走的路线“ai engineering from scratch”这个话题,我其实一开始是带着怀疑的——两年前市面上讲AI的课程,十个里面有九个都在教你怎么调sklearn、怎么跑通一个pytorch的官方demo&#xff… · 2026/11/2 20:57:01

机器人学习数据格式转换工具lerobot_convertor详解
机器人学习数据格式转换工具lerobot_convertor详解

1. 项目概述 lerobot_convertor 是一个专为机器人学习领域设计的轻量级数据格式转换框架,它的核心功能是将各类机器人数据集统一转换为 LeRobot 兼容格式。这个工具解决了多源数据标准化处理的痛点,特别适合需要快速整合不同来源数据集进行模型训练的研究… · 2026/11/2 20:57:01

能源行业零信任与纵深防御融合架构实践
能源行业零信任与纵深防御融合架构实践

1. 能源行业安全架构的现状与挑战能源行业作为国家关键基础设施的核心组成部分,其信息系统安全直接关系到国计民生。近年来,随着数字化转型的深入,能源企业面临着前所未有的安全挑战。传统基于边界防护的安全架构在面对新型威胁时显得力不从心… · 2026/11/2 20:57:01

从零构建AI工程体系:Python/TS/Rust/Julia四语言协同实践
从零构建AI工程体系:Python/TS/Rust/Julia四语言协同实践

1. 为什么“从零构建AI工程体系”不是一句空话,而是当前最真实的生存需求“ai-engineering-from-scratch”这个标题乍看像一门课程名,或是某本技术书的副标题。但如果你最近半年深度参与过至少一个落地AI项目——无论是给内部业务部门搭一个能跑通的RAG知… · 2026/11/2 20:57:01

Doma框架常见问题排查:编译期SQL校验与工程实践
Doma框架常见问题排查:编译期SQL校验与工程实践

接手一个用Doma框架维护的存量项目时,最先撞上的往往不是业务逻辑,而是满屏的编译期报错:SQL文件找不到、绑定变量对不上、生成的DAO实现类飘红。Doma这套Java数据库访问框架的思路很特别,它把SQL从Java代码里彻底抽出来放进独立的… · 2026/11/2 20:57:01

VGG19图像分类迁移学习:冻结策略与验收避坑指南
VGG19图像分类迁移学习:冻结策略与验收避坑指南

简介:面向智能计算系统课程实验与深度学习部署入门者,这份实验4-1资料围绕VGG19图像分类任务,提供从卷积网络推理到硬件加速评估的实践素材,适合需要理解模型量化与不同计算平台性能差异的学习者。压缩包共4个文件,由3… · 2026/11/2 20:56:00

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 4:42:45

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 5:17:18

雷达信号调制技术解析:从LFM到伪线性调频原理与应用
雷达信号调制技术解析:从LFM到伪线性调频原理与应用

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 1:01:15

基于MAX14431与TM4C123的工业SPI隔离电路设计全攻略
基于MAX14431与TM4C123的工业SPI隔离电路设计全攻略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 1:01:15

PLFM_RADAR:相位线性调频雷达信号处理框架
PLFM_RADAR:相位线性调频雷达信号处理框架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 1:01:15

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 4:42:45

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 5:17:18

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码