时间复杂度最小的最短路径算法?由这个想到的

本文探讨了使用物理模拟方法解决有向图中两点间最短路径问题的创新思路,最终揭示了这种方法实际上等效于Dijkstra算法。通过简化场景和逐步分析,展示了如何从直观的物理实验抽象出高效的算法实现。同时,阐述了在边长不同的情况下,模拟方法的局限性及改进策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近看书发现了一段很有意思的东西,好像是谷歌的工程师发表在谷歌黑板报里的:

       有一次,我笨得忘记了该如何在一个复杂的有向图中找出两点之间的最短路径。身边的一位工程师很郑重地告诉我说:“你知道吗?解决这个问题有两种方法,聪明人的方法和笨人的方法。聪明人的方法是:照着算法教科书的讲解,实现那个时间复杂度相当大的名叫嘀嘀哒嘀哒的最短路径算法。笨人的方法时间复杂度最低:找一堆线头来,按照有向图的结构连成一张网,然后一手拿一个顶点,向两边一抻,中间拉直了的那条路就是最短路径呀。”

       “哇噻!笨是一种多么伟大的品格呀!”我眩晕得说不出话来。于是,我们这两个自认为足够笨的工程师足足花了两周的时间,用计算机程序模拟了不同材质的细线在北半球的重力条件下相互连接并在两个反方向作用力的影响下向两
边伸展的整个物理过程,然后以此为基础实现了时间复杂度最小的最短路径算法。——瞧,在 Google,什么东西都可以自己动手实现,什么东西也都可以推陈出新,我们的杰出表现就是最好的证明。

乍一看让人觉得甚是巧妙,不过总觉得有什么不对的地方,思索一番,是有此文


当然这个场景有个前提,边都是无向边,否则就不好模拟了。

我们来考虑一下这样一个模拟程序应该怎么写,就忽略什么细线的材质和北半球的重力条件了,先试着简化一下场景,因为我们想求源点S和目标点T之间的最短距离,只需要把源点S钉在墙上,其他点都挂在S下面,假设点不占空间,此时受重力作用,S和T的距离就是它们的最短距离了,这个问题应该是和原问题等价的,拉伸方向不同而已。
这里写图片描述

贪心模拟

这个东西怎么模拟呢?一时没有头绪,我们就再简化一下问题,假设每条边的长度都为1,这些就简单了嘛:最后挂出来的效果肯定是分层的,和S距离为1的点在第一层,和S距离为2的点在第二层:我们先把直接和S相连的点捋直了挂在下面,这些点肯定就是最短距离了,这是第一层;然后把能连到第一层并且还没挂上去的点挂到第二层,最后挂到T的时候结果就出来了。
这里写图片描述
其实很清楚了,这不过就是简单的宽搜(BFS)而已,忽略掉同层相连的边之后整个图就简化为了一个树,树的根就是S,最短距离就是T点的深度,算法时间复杂度是O(M+N)的,M为边的数量,N为点的数量。

目前还不错,目前已知的最优两点间最短路径算法是O(M + N log N)的,可是别忘了我们现在是在特殊条件下:每条边的长度都是相同的

如果边的长度各有不同,会出现什么情况呢?别的先不管,我们照例挂上第一层的点(左1):
这里写图片描述
嗯,有问题了,这些点能拉直挂着的前提条件是此时它到源点的距离已经是最短的,所以当边的长度不定的时候,点和点直接相连的边不一定是最短距离!以上图的C点为例,通过一个中间节点挂上去的才是最短距离!(右2)

好像我们的方法用不上了,看看能不能改进解决呢?嗯,我们是要保证挂上去的就是最短距离,其实很好办嘛,我们一次只挂一个上去!

首先把直接连到S点且最近的那个点(假设是a)挂上去,此时肯定是最短距离;然后我们来挂第二个点,会有两种情况:1.这个点是直接挂在S上的;2.这个点是挂在a上的。此时我们就有了这两个候选集合,只需要选出其中到源点距离最短的点挂上即可(这个距离如果是和S连直接就是边长度,如果是和a连的就加上a到S的距离,假设我们选到了b),然后在下一步需要从三个候选集合(和S连的,和a连的,和b连的)里选择……

这样就满足了我们要求的前提条件,伪代码如下:

f = {}; 表示节点到边的最短距离
now = s;
f[s] = 0;
while (now!=t):
    now <- 目前离S最近的点,通过筛选候选集合选出
    f[now] = f[q] + e[q][now]; //假设now通过q连到源点S

嗯,搞定收工!算算复杂度,找距离最小的点可以用小根堆,老师教过,这是O(log n)的,外面还有个N层循环,还需要扫描边…………等等,话说这个描述咋这么眼熟啊?这不就是Dijkstra算法~~ ಥ_ಥ ~~,所以不管怎么玩,这个算法的复杂度最好就是O(m + n log n)的。

真模拟

看来这样类似贪心的模拟没用了啊,不得不上真家伙了,真实模拟一个网络来钉一次墙!

嗯,主要是靠脑暴,真要写一个就太麻烦了,我们回到原始的问题,也就是把网络平着抻直的场景
这里写图片描述
为了模拟拉这个动作,我们把S固定在墙1上,T固定在墙2上,然后一点一点把墙2从墙1的位置开始往右边挪动……

1.要真模拟,那么线和点都变成了实体,但它们都是没有碰撞体积的。

2.所谓模拟,其实就是按时间步去模拟,根据实体的受力情况改变它的位置,毕竟计算机的世界是离散的嘛,我们需要一点点改变点的未知以保证线不被拉断(为了防止线被拉断,当线被拉直的时候会产生拉力,这就是力的传递)。

3.所以每个时间步需要去扫描每个节点,力的来源一个是重力,一个是线的拉力,因此你还需要访问到所有的线,这里的复杂度已经到了O(M+N)。

4.最后我们要确定的其实就是整个系统稳定下来(挂稳不乱晃悠了)需要的时间步应该是多少。

因为我们的模拟是每次去扫描节点,但其实节点是不知道整个系统的真实情况的,比如我移动了一下墙2,所有的信息(力)都需要从T点传递过来:首先是T的邻点感知到了T位置的变化,因此产生了力的变化,这些点会受拉力移动一下,然后传播下一层的点再感知到这个变化,再根据受力情况改变自己的状态……and so on.

所以这个时间步其实是和树的深度(就是我们假模拟一开始用的那个东西)有关的!力的传递是需要时间的!所以时间步的复杂度其实是O(N),ps:真实世界的情况~~zhihu.com 力的传递有速度吗?

所以这个模拟方法的复杂度应该是O((M+N)*N)的,并不是所谓的时间复杂度最小的最短路径算法

后记

嗯,以上纯粹是我的推论~~~

因为也没实际看到原作者的实现,但我认为从理论上来说所谓模拟方法的复杂度肯定不可能低于目前已知最优算法的,所以工程狮还是自high居多,虽然看起来是很有说服力。

以上文章有问题还请指出,这个话题讨论起来我觉得还是蛮有意思的

<think>嗯,用户需要解决实时快速生成算法的问题,并且希望用MATLAB实现两个优化路径算法。首先,我得明确用户的具体需求是什么。实时快速产生算法通常用于需要即时响应的场景,比如机器人导航、自动驾驶或者实时物流调度。用户可能是在开发这类应用,需要一个能够在短时间内计算出优路径的算法。 接下来,用户要求列出两个可以用MATLAB编程的优化路径算法,并详细说明它们的编程难度、时间复杂度以及所需的库。首先,我需要确定哪些路径规划算法适合实时应用,同时MATLAB有足够的支持库或工具箱来简化实现。 第一个想到算法是A*算法。A*是一种广泛使用的路径规划算法,结合了Dijkstra算法和启发式搜索,效率较高,适合实时应用。它的时间复杂度取决于启发式函数的质量,通常在O(b^d)左右,其中b是分支因子,d是深度。MATLAB中实现A*可能需要处理图的表示、优先队列等结构,可能需要自己实现部分功能,但总体来说难度适中。 另一个候选算法是Dijkstra算法,虽然它在没有启发式的情况下时间复杂度较高(O(V^2)),但可以通过优先队列优化到O(E + V log V)。不过,Dijkstra可能不如A*高效,特别是在大规模图中。不过用户可能需要一个基础的算法作为对比,或者用于特定场景。 再考虑其他可能性,比如RRT(快速随机探索树),适用于高维空间和复杂环境,但实时性可能不如A*,而且实现起来可能更复杂,尤其是需要处理随机采样和碰撞检测。不过用户提到要实时快速,RRT的变种如RRT*可能更适合,但时间复杂度可能较高。 或者,可以考虑动态规划方法,比如在已知环境中预计算路径,但实时性可能依赖于预处理,可能不符合实时生成的要求。 综合考虑,A*和Dijkstra是比较基础且适合实时场景的算法,而RRT可能在复杂环境中更适用,但编程难度和时间复杂度可能更高。用户可能更需要平衡实时性和复杂性的算法,所以选择A*和Dijkstra作为两个例子。 接下来,需要确认MATLAB中是否有现成的库或函数支持这些算法。例如,A*可能需要图论工具箱,而Dijkstra在MATLAB中可以通过graph和shortestpath函数实现。对于A*,可能需要手动实现启发式函数,或者利用现有的函数。此外,MATLAB的Robotics System Toolbox可能提供路径规划的工具,比如mobileRobotPRM或plannerAStarGrid,但用户可能需要根据具体环境进行调整。 关于编程难度,A*需要理解启发式函数和优先队列的实现,而Dijkstra在MATLAB中可能有更直接的函数支持,所以Dijkstra可能更容易。不过如果使用内置函数,两者都可能简化。需要查证MATLAB的文档,确认是否有现成的A*实现,比如在Robotics Toolbox中的相关函数,这样可以降低编程难度。 时间复杂度方面,A*在优情况下比Dijkstra更快,尤其是在有良好启发式函数时。而Dijkstra的时间复杂度在优化后可以接受,但可能在大型图中较慢。需要准确描述两者的复杂度,并指出它们的适用场景。 后,需要列出每个算法需要用到的库,比如MATLAB的图论工具箱、Robotics System Toolbox,或者是否需要自己实现某些部分。例如,A*可能需要Robotics System Toolbox中的plannerAStarGrid,而Dijkstra可以使用MATLAB自带的graph和shortestpath函数,属于基础功能,可能不需要额外工具箱。 总结下来,两个算法选择A*和Dijkstra,分别分析它们的实现难度、时间复杂度和所需库。需要确保信息准确,参考MATLAB的官方文档确认函数和工具箱的支持情况。</think>### 针对【实时快速路径生成算法】问题的 MATLAB 实现方案 --- #### **算法 1:A* 算法** - **应用场景**:网格地图导航、机器人路径规划、游戏 AI。 - **编程难度**:★★★☆☆ - 需手动实现启发式函数(如欧氏距离、曼哈顿距离)。 - 需管理优先级队列(可用 MATLAB 内置 `priorityqueue` 对象或自定义堆结构)。 - 需处理地图的网格或图结构(可借助 `binaryOccupancyMap` 或 `graph` 对象)。 - **时间复杂度**: $$O(b^d)$$ 其中 \(b\) 为分支因子,\(d\) 为最短路径深度。实际性能高度依赖启发式函数的质量。 - **关键 MATLAB 库**: - **Robotics System Toolbox**(提供 `plannerAStarGrid` 预定义函数,简化网格地图实现)。 - **Navigation Toolbox**(支持复杂地图建模)。 - 基础库:`graph`、`priorityqueue`(需 MATLAB R2023a+)。 --- #### **算法 2:Dijkstra 算法** - **应用场景**:无权图最短路径、网络路由、静态环境导航。 - **编程难度**:★★☆☆☆ - 可直接使用 MATLAB 内置函数 `shortestpath`(语法:`[P,d] = shortestpath(G,start,end)`)。 - 需构建图对象 `graph` 或邻接矩阵,无需额外优化逻辑。 - **时间复杂度**: $$O(|E| + |V|\log|V|)$$ 其中 \(|E|\) 为边数,\(|V|\) 为节点数。使用优先队列优化后接近理论下限。 - **关键 MATLAB 库**: - 基础库:`graph`(无需额外工具箱)。 - 可选:`Statistics and Machine Learning Toolbox`(用于复杂图数据分析)。 --- ### **对比与选择建议** | 算法 | 实时性 | 适用场景 | 编程复杂度 | 库依赖 | |------------|--------|--------------------|------------|-------------------------| | **A*** | 高 | 动态环境、启发搜索 | 中等 | Robotics System Toolbox | | **Dijkstra** | 中 | 静态图、全局优 | 低 | 基础库 | - **推荐组合**: 若需快速部署,优先使用 `Dijkstra` + 内置 `shortestpath`; 若环境动态复杂,选择 `A*` + `plannerAStarGrid`(需验证工具箱许可)。 --- ### **代码示例(A* 算法简版)** ```matlab % 创建网格地图(10x10 无障碍) map = binaryOccupancyMap(10,10,1); % 定义起点和终点 start = [1,1]; goal = [10,10]; % 初始化 A* 规划器 planner = plannerAStarGrid(map); % 生成路径 path = plan(planner, start, goal); % 可视化 show(planner); ``` --- ### **注意事项** 1. **实时性优化**: - 限制地图分辨率或节点数量。 - 预计算静态环境数据(如使用 `navGraph`)。 2. **硬件加速**: 可调用 `parfor` 或 GPU 计算工具箱(如 `gpuArray`)加速大规模计算。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值