多单位寻路算法,寻找最优解

对于单个单位的寻路可以使用A*算法。但是在实际应用中往往出现多个单位同时移动的场面,而且它们会互相影响,阻碍对方的移动。所以一旦冲突,之前为每个单位计算出的路径就会失效。

一种流行的解决方法是发现冲突的时候重新计算路径。还有定期重新计算的等等。这些都是动态调整的方案,最后形成的路径并非是最优的。虽然这些次优解可以满足大部分场景的需要,但是有没有办法计算出最优解呢?毕竟很多动态调整的算法会有失败的可能。

我们可以把一个最小时间单位(回合)中每个单位的可能移动的组合列出来作为节点,放入搜索树中,然后再用A*算法进行搜索。但是在方格地图中一个单位可以有最多5或者9(带斜线)种不同的移动方法,其中包括静止不动。2个单位就有5x5或9x9种组合。随着要考虑的单位数的增加,组合数会爆炸。这时我们可以把一个回合再分解到一系列单个单位的移动,把单个移动作为节点。这样一旦发现某些条件不满足,比如两个单位有冲突,就可以关闭当前节点,不继续生成组合,从而实现对搜索树进行剪枝。由于一个回合中各单位的移动实际并没有优先次序,而我们现在的处理是一个单位一个单位进行,所以先被处理的单位不需要检查和后面单位的冲突,只有后面的单位需要检查和前面单位的冲突。当然为了成功剪枝,优先处理哪些单位也是值得考虑的。可以按某种优先级排序,比如越接近目标的可以优先处理。

举个例子,假定一个2x2的地图,有两个单位A在坐标1,0处,B在坐标0,1处,都想要移动到坐标1,1处。那么我们按先处理A后处理B的次序生成节点。假定[]表示计划的移动列表,{}表示未计划的单位列表。那么搜索树可以表示如下:

                                                []{A10,B01} //初始状态

                                                       /                                \                    \

[A向下]{B01}                         [A不动]{B01}未展开       [A向左]{B01}未展开

                          /                     |       \

[A向下B向右]{}冲突,剪枝      [A向下B不动]{}             [A向下B向上]{} 未展开

                                                     |

 []{A11,B01}     ->     []{B01} 回合1结束,结算位置,A到达目的地,被移走,然后进行下一轮。

                                                                          /                   \                     \

 [B向右]{}      [B不动]{}未展开    [B向上]{}未展开

                                                                     |

[]{} 回合2结束,结算位置,B到达目的地,被移走。列表为空,达成目标状态。

另一个优化是,虽然我们可以生成一个单位的所有移动方法,但是我们并不急于把所有的移动都作为节点放入open list中,而只选1~2个最有可能成功的。当前节点并不关闭,并且维护一个列表,记录有哪些移动已经展开过了。这样可以有效减少open list中节点的数量。假定<>为未展开的移动,上面的例子可以用如下表示:

                                                                        []{A10,B01} //初始状态    -> []<A不动, A向左>{}

/

[A向下]{B01}  ->    [A向下]<B向上>{} 

                                     /                     |       

[A向下B向右]{}冲突,剪枝      [A向下B不动]{}  

                                                                     |

 []{A11,B01}     ->     []{B01}  ->   []<B不动,B向上> 回合1结束,结算位置,A到达目的地,被移走,然后进行下一轮。

                                                                                                      |        

[B向右]{}

                                                                                                      |

[]{} 回合2结束,结算位置,B到达目的地,被移走。列表为空,达成目标状态。

关于A*搜索的启发函数,我们当然可以求出每个单位的manhattan距离、diagonal距离或者duclidean距离,然后求和作为每个节点的启发值。更好的启发值可以用RRA*(Reverse Resumable A*)算法来获得。也就对目标点到当前点执行一次普通A*搜索,来获得(不计移动单位的障碍)的实际距离。这个距离比前面提到的估算算法要准确得多。RRA*搜索生成的open list是可以重用的,实际上开销并不大。当然对多个目标点,我们需要维护各自的open list。

具体实现可以参考github.com/silmerusse/fudge_pathfinding中的例子。对于相对简单的地图和较少的单位,最优解是可以很快求出的。但是对复杂度高的地图和较多单位,则需要花费较多时间和内存空间。

时间: 2024-10-16 12:09:20

多单位寻路算法,寻找最优解的相关文章

C#实现简单的AStar寻路算法

1.算法实施模型 在我看来,最简单最基础的寻路环境是:在一片二维网格区域中存在一些围墙(Block),在起始点和终点之间保持连通的前提下寻找一条最佳路径. 2.算法原理 详细介绍有很多,可参考网址:http://www.policyalmanac.org/games/aStarTutorial.htm,浅显易懂,重点是理解"启发式搜索"的概念.下面谈谈我自己的理解,如果是第一次接触A*寻路算法,还是先老老实实看完给出的参考网址吧(当然也可以参考相关的中文介绍资料). 在一片二维网格中,

这是一个真正靠谱的寻路算法

绝对没有其他看起来高大上 给别人讲都将不明白的理论.管你 人工智能 啥的 ,还有一百度一大篇的a*算法 ,其实大部分文章的理论都是讲不通的 或者没有讲清楚 更别说代码.做事刨根问底的牛脾气又上来了. 两周前 偶然原因接触到了寻路算法 于是百度 找到了a* .讲来将去大概意思就是持续性的找离目标近的节点 并且走过的节点不能重复走.反正百度搜a*算法 一搜一大片.在很简单的障碍的情况下是没问题 : 但是拐个弯就不行了,不是找最近的么,我让你一直找最近的. 直接迂在里面出不来了: 期间我曾经想过为什么

[转] A*寻路算法C++简单实现

参考文章: http://www.policyalmanac.org/games/aStarTutorial.htm   这是英文原文<A*入门>,最经典的讲解,有demo演示 http://www.cnblogs.com/technology/archive/2011/05/26/2058842.html  这是国人翻译后整理的简版,有简单代码demo,不过有些错误,讲得很清晰,本文图片来自这篇 http://blog.csdn.net/b2b160/article/details/4057

js实现A*寻路算法

这两天在做百度前端技术学院的题目,其中有涉及到寻路相关的,于是就找来相关博客进行阅读. 看了Create Chen写的理解A*寻路算法具体过程之后,我理解A*算法的原理,不得不说作者写的很好,通熟易懂,图片也做的很好,可见作者在这上面是花了心思的.如果让我写,我是写不来这么好的. 唯一的不足就是,因为我学的是js,因此最后给我的源码我是用不了的......因此才有自己写一篇的打算,方面学习js人的学习.然而前面的描述我就借用他的了,因为如果然我的表达能力实在是太渣了. 简易地图 如图所示简易地图

关于A*寻路算法的认识

最近要参加学校的APP比赛,我们组做的是一个3D迷宫的小APP,我负责的是迷宫的生成与寻路. 寻路算法选择的是A*寻路算法,具体参考的是下面的这篇博客. 本文主要是谈谈自己对A*算法的理解,具体细节,上文链接以及讲的很详细了. http://www.cnblogs.com/technology/archive/2011/05/26/2058842.html 关于A*算法的实现我是用的广度优先搜索这种比较常见的实现模式. 那么关于这两者之间的关系是怎么样呢? 个人理解的是A*算法其实是一种带有路径

A*寻路算法的lua实现

一.问题概述 游戏中有敌我双方,有四十个方格,当轮到我方武将行动的时候,要先显示出我方武将可以行动的方位,这个就涉及到我方武将的行动力的大小来决定,预先做出路径的预算.这里还要考虑敌方以及地标(例如:炸弹.势头)的阻挡,以及特殊方格对武将行动力的消耗以及敌方的间隔阻挡规则. 当碰到这个问题的时候,问老大选择用什么寻路算法,他推荐的是Dijstra算法,但我看了之后感觉还不是很适合我的需求,第一:我觉得Dijstra算法是有向图的最佳路径选择,节点之间路径长度必须先知晓,但我这里四十个方格如果要两

A星寻路算法以及C++实现

A星寻路算法真是我一生接触的第一个人工智能算法了... A星寻路算法显然是用来寻路的,应用也很普遍,比如梦幻西游...算法的思路很简单,就是在bfs的基础上加了估值函数. 它的核心是 F(x) = G(x) + H(x) 和open.close列表: G(x)表示从起点到X点的消耗(或者叫移动量什么的),H(X)表示X点到终点的消耗的估值,F(x)就是两者的和值.open列表记录了可能要走的区域,close列表记录了不会再考虑的区域.我们每次都选F值最小的区域搜索,就能搜到一条到终点的最短路径,

A星寻路算法-(入门级)

你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法的文章,但是大部分都是提供给已经了解基本原理的高级开发者的. 本篇教程将从最基本的原理讲起.我们会一步步讲解A星寻路算法,幷配有很多图解和例子. 不管你使用的是什么编程语言或者操作平台,你会发现本篇教程很有帮助,因为它在非编程语言的层面上解释了算法的原理. 现在找下到达一杯咖啡因饮料和美味的零食的最

寻路算法A*, JPS(跳点搜索)的一些杂谈

A*是一个比较经典的启发式寻路算法.是基于dijkstra算法,但是加入了启发函数,使路径搜索效率更高.实现起来很简单.不过要做到通用性高,比如支持各种不同类型的地图,甚至不仅仅是地图,而是个图结构如解决拼图游戏N-puzzle会用到的,就需要多花点心思.用C++实现的话,可以使用模板来适应不同的需要.也可以使用类继承. template <typename NodeType, typename CostType, typename Heuristic> static vector<No