A* 寻路的八个变种
变种 1 - 束搜索(Beam Search)
在 A* 算法的住循环中,OPEN 集存储可能需要搜索的节点,用来以查找路径。
束搜索是 A* 的变体,它限制了OPEN集的大小。
如果集合变得太大,则丢弃给出良好路径的最差机会的节点。
束搜索的一个缺点是你必须保持你的设置排序这样做,这限制了你选择的数据结构的种类。
变种 2 - 迭代加深(Iterative Deepening)
迭代加深是一种在许多AI算法中使用的方法,以近似答案开始,然后使其更准确。
该名称来自游戏树搜索,您可以在其中查看前面的一些移动(例如,在国际象棋中)。
您可以通过向前看更多动作来尝试加深树木。
一旦你的答案没有改变或改善很多,你就会认为你有一个非常好的答案,当你试图让它再次变得更准确时它不会改善。
在 IDA* 中,“深度”是 f 值的截止值。
当 f 值太大时,甚至不考虑节点(即,它不会被添加到 OPEN 集)。
第一次通过你处理很少的节点。
每次后续传递,都会增加您访问的节点数。
如果您发现路径有所改善,那么您将继续增加截止值;否则,你可以停下来。
我个人认为在游戏地图上不太需要用 IDA* 查找路径。
因为 ID 算法倾向于增加计算时间,同时减少内存需求。
然而,在地图寻路中,“节点”非常小 - 它们只是坐标。
我没有看到节约存储这些节点有什么巨大优势。
变种 3 - 动态加权(Dynamic Weighting)
通过动态加权,您可以假设——
在搜索开始时,快速到达目的地所在区域更重要;
在搜索结束时,得到到达目标的最佳路径更重要。
有一个与启发式相关的权重(w >= 1)。
随着你越来越接近目标,你减轻了权重;这降低了启发式的重要性,并增加了路径实际成本的相对重要性。
变种 4 - 带宽搜索(Bandwidth Search)
有一些人可能觉得有用的带宽搜索有两个属性。
这种变化假设 h 是高估的,但它并没有高估超过一些数e。
如果您的搜索就是这种情况,那么您获得的路径的成本不会超过最佳路径的成本超过e。
再次,您的启发式越好,您的解决方案就越好。
您获得的另一个属性是,如果您可以删除OPEN集中的某些节点。
每当 h + d 大于路径的真实成本(对于某些 d ),您可以丢弃任何 f 值至少比 OPEN 中最佳节点的 f 值高 e + d 的节点。
这是一个奇怪的属性。
你有一个很好的 f 值“带宽”;这个频段以外的所有东西都可以丢弃,因为可以保证它不会走在最佳路径上。
奇怪的是,您可以对这两个属性使用不同的启发式方法,但事情仍然有效。
您可以使用一个启发式方法来保证您的路径不是太糟糕,另一个用于确定 OPEN 集中的内容。
注意:
带宽搜索看起来可能有用,但在游戏行业很少使用到。
搜索 Google 以获得更多信息,尤其是相关论文。
变种 5 - 双向搜索(Bidirectional Search)
您可以不从开始到结束搜索,而是并行开始两次搜索,一次从头到尾,一次从完成到开始。
当他们见面时,你应该有一条好路。
在某些情况下,这是一个好主意。
双向搜索背后的想法是搜索结果在地图上扇出的“树”。
一棵大树比两棵小树要糟糕得多,所以最好有两棵小树。
从面对面的变化将两个搜索链接在一起。
不是选择最佳前向搜索节点【 g(start, x) + h(x, goal) 】或最佳后向搜索节点【 g(y, goal) + h(start, y) 】
该算法选择具有最佳【g(start, x) + h(x, y) + g(y, goal)】的节点对。
重定向方法(retargeting approach)放弃了向前和向后方向的同时搜索。
相反,它会在短时间内执行前向搜索,选择最佳前向候选者 N;
然后在终点执行后向搜索,搜索的目标不是起点,而是最佳前向候选者 N。
过了一会儿,它选择了一个最好的后向候选人 M ,并执行从 N 到 M 的前向搜索。
这个过程一直持续循环,直到两个候选人是同一个点。
Holte,Felner,Sharon,Sturtevant 在 2016 年的论文《具有近似最优节点扩展的前端双向启发式搜索》 是最近的结果,具有接近最优的 A* 双向变体。
Pijls 和 Post 在 2009 年的论文 《另一种用于最短路径的双向算法》 提出了一种比平衡双向搜索运行得更快的不平衡双向 A* 。
变种 6 - 动态 A*(Dynamic A*)和 终身规划 A*(Lifelong Planning A*)
A* 的变体允许在计算初始路径之后改变世界。
D* 适用于没有完整信息的情况。
如果你没有所有的信息,A* 会犯错误;D* 的贡献在于它可以在不花费太多时间的情况下纠正这些错误。
LPA* 旨在用于成本变化时使用。
使用A*,路径可能会因地图的更改而失效;LPA *可以重复使用先前 A* 的计算来生成新路径。
但是,D* 和 LPA* 都需要很大的空间 —— 需要保存在最佳路径周围的很多节点的内部信息(OPEN / CLOSED集,路径树,g值)
然后当地图改变时,D* 或 LPA* 会告诉您是否需要调整路径以考虑地图更改。
对于具有大量移动单位的游戏,您通常不希望保留所有这些信息(因为太大),因此 D* 和 LPA* 不适用。
它们是专为机器人设计的,如果只有一个机器人 —— 您不需要将内存重用于其他机器人的路径。
如果您的游戏只有一个或少数单位,您可能需要试试 D* 或 LPA* 。
变种 7 - 跳点搜索(Jump Point Search)
许多加速 A* 的技术实际上都是关于减少节点数量。
在具有统一成本的方形网格中,一次一个地查看所有单独的网格空间是相当浪费的。
一种方法是构建关键点(例如角点)的图形并将其用于寻路。
但是,如果您不希望预先计算航点图,那就可以了解一下跳转点搜索,这是 A* 的变体,可以在方格网格上向前跳跃。
当考虑当前节点的子节点可能包含在 OPEN 集中时,跳转点搜索会向前跳到从当前节点可见的远端节点。
每个步骤都更昂贵,但它们更少,减少了 OPEN 集中的节点数量。
有关详细信息,请参阅此博客。
此文章提供了一个很好的可视化程序用来解释。
另请参阅矩形对称缩减,它可以分析地图并将跳转嵌入到图形本身中。
这两种技术都是为方形网格开发的。
这个网站是为六边形网格扩展的算法。
变种 8 - Theta*
网格用于寻路,是因为地图是在网格上制作的,而不是因为我们实际上想要在网格上移动。
如果给出关键点(例如角点)而不是网格的图形,A* 将运行得更快并产生更好的路径。
但是,如果您不想预先计算角点图形,则可以使用在方形网格上运行的 A* 变体 Theta* 来查找不严格遵循网格的路径。
在构建父指针时,如果该节点与祖先节点有一条视线,互相可见,那么 Theta* 将该节点直接指向祖先节点,并跳过他俩中间的节点。
与路径平滑不同,路径平滑在 A* 找到路径之后拉直路径;而 Theta* 可以在 A* 过程中分析这些路径的,是 A* 的一部分。
这可以得到比将网格路径后处理成任意角度路径更短的路径。
这篇文章是对该算法的合理介绍;这里是 Lazy Theta*。
Theta *的想法很可能也适用于导航网格。
另请参阅 Block A*,它声称通过使用分层方法比 Theta* 快得多。
A* 寻路的八个变种的更多相关文章
- 如何在Cocos2D游戏中实现A*寻路算法(八)
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...
- 使用PyTorch进行情侣幸福度测试指南
欢迎关注磐创博客资源汇总站: http://docs.panchuang.net/ 欢迎关注PyTorch官方中文教程站: http://pytorch.panchuang.net/ 计算机视觉–图像 ...
- kb-01-a<简单搜索--dfs八皇后问题变种>
题目描述: 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的 ...
- 一个高效的A-star寻路算法(八方向)(
这种写法比较垃圾,表现在每次搜索一个点要遍历整个地图那么大的数组,如果地图为256*256,每次搜索都要执行65535次,如果遍历多个点就是n*65535,速度上实在是太垃圾了 简单说下思路,以后补充 ...
- A*寻路算法的探寻与改良(三)
A*寻路算法的探寻与改良(三) by:田宇轩 第三分:这部分内容基于树.查找算法等对A*算法的执行效率进行了改良,想了解细 ...
- 一步一步开发Game服务器(五)地图寻路
目前大多数使用的寻路算法有哪些? 目前市面上大部分游戏的寻路算法是A*,或者B*. A*通常所说的是最优算法也就是寻找最短路径.B*碰撞式算法也就是,也就是不断的去碰撞能走就走,不管是不是绕路.当然以 ...
- A星寻路算法介绍
你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法 ...
- A*寻路算法
对于初学者而言,A*寻路已经是个比较复杂的算法了,为了便于理解,本文降低了A*算法的难度,规定只能横竖(四方向)寻路,而无法直接走对角线,使得整个算法更好理解. 简而言之,A*寻路就是计算从起点经过该 ...
- js实现A*寻路算法
这两天在做百度前端技术学院的题目,其中有涉及到寻路相关的,于是就找来相关博客进行阅读. 看了Create Chen写的理解A*寻路算法具体过程之后,我很快就理解A*算法的原理.不得不说作者写的很好,通 ...
随机推荐
- nginx反向代理跨域基本配置与常见误区
最近公司前后端分离,前端独立提供页面和静态服务很自然的就想到了用nginx去做静态服务器.同时由于跨域了,就想利用nginx的反向代理去处理一下跨域,但是在解决问题的同时,发现网上有些方案的确是存在一 ...
- NPOI保存到服务器和导出到客户端
保存到服务器 <a class="easyui-linkbutton" href="javascript:void(0);" onclick=" ...
- [HNOI2005]汤姆的游戏
嘟嘟嘟 直接O(n ^ 2)暴力判断就行了. 对于圆,判断该点和圆心的距离是否小于半径. 然而为啥我这么写编译不过: scanf("%lf%lf%lf%lf", &a[++ ...
- layui弹出层之应用实例讲解
从酒店管理系统到智能门锁及其现在的资源共享平台,layui框架,我们团队用的比较多的就是这个layui弹出层. layui弹出层,除了页面iframe层我们比较常用还有就是表单校验和其他相关的友好提示 ...
- python开发_stat
当我们使用os.stat(path)获取一个文件(夹)信息的时候, os.stat(path)本身返回的是一个元组如: nt.stat_result(st_mode=33206, st_ino=203 ...
- ra寄存器定位core
$ra寄存器中存入的是pc的值(程序运行处的地址),调用函数时,在跳转前,必须保存当前地址(pc的值),以便后来返回.jal $ra 保存后跳转,jr $ra,返回到跳转前,通过$ra保存进入上层栈地 ...
- .NET 操作 EventLog(Windows事件日志监控)(转载)
操作Windows日志:EventLog 如果要在.NET Core控制台项目中使用EventLog(Windows事件日志监控),首先需要下载Nuget包: System.Diagnostics.E ...
- 笔记2:MYSQL 表操作
一.表约束 1.非空约束:not null 作用:定义表的某一列不能为空. >> alter table 表名 modify 列名 int not null; "添加非空约束&q ...
- Linux基础-6.系统的启动过程
Linux启动时我们会看到许多启动信息 Linux系统的启动过程并不是大家想象中的那么复杂,其过程可以分为5个阶段: 内核的引导 运行init 系统初始化 建立终端 用户登录系统 init程序的类型: ...
- Python的open函数文件读写线程不安全,logging模型文件读写线程安全!
工作中遇到的问题:如何在多线程的程序中同时记录日志? 最初图省事,使用了最原始的open函数来写日志,因为开始使用的写文件模式的是追加('a'),发现并没有线程不安全的现象,各个线程的的日志信息都写入 ...