A*寻路算法的优化与改进

提要

通过对上一篇A*寻路算法的学习,我们对A*寻路应该有一定的了解了,但实际应用中,需要对算法进行一些改进和优化。

Iterative Deepening Depth-first search- 迭代深化深度优先搜索

在深度优先搜索中一个比较坑爹情形就是在搜索树的一枝上没有要搜的结果,但是却非常深,甚至深不见底,这样就根本搜索不到结果。为了防止这种情况出现,就出现了Iterative Deepening的思想。

迭代深化搜索(Iterative deepening search, IDS)或者(迭代深化深度优先搜索,Iterative deepening depth-first search)是一种常用的搜索机制,经常使用在深度优先搜索中.通过逐渐地提高深度限制搜索(Depth-limited search)的深度限制(depth limit)——从1开始,然后2,一直到找到目标结点位置为止——迭代深化搜索能够找出最好的深度限制.深度限制搜索指的是在深度优先搜索中,引入深度限制limit,如果从根结点出发到结点N的深度为limit,那么N被当做没有子结点的叶结点那样处理.

找一棵树来具体看一下。

需要找ee节点。

首先把深度限制设置为1,则要搜索的树为

对其进行深度优先搜索,没搜到,增加深度限制为2.

进行DFS还是没搜索到,继续增加深度限制到3.

进行DFS,Bingo,找到。

和直接用DFS一样啊,看起来傻傻的? No!

这个方法首先规避了最开始说的DFS深度的问题,相对于BFS一般需要存储产生的所有结点,占的存储空间要比深度优先大得多,ID-DFS它的内存占用又少很多。再来看看时间复杂度.

迭代深化搜索也许看起来比较浪费时间,因为状态有可能被多次产生.但是事实并非如此,因为大多数的结点处在底层,而底层结点的搜索次数很少.对于一个深度为d,分支因子为b的树,.最多需要搜索的结点个数为:

故此迭代深化搜索的时间复杂度和深度优先搜索的一样是O( bk)

So... 这个算法是两种搜索方法的折中,BFS能搜索到的,它就一定能搜到,而且不用那么多的空间,只需牺牲一点点的时间(相同的节点可能要访问很多次)。

下面是一个一般一些的例子,包含了三种算法的对比。

Iterative Deepening A*

迭代延伸A*可以简写成IDA*,用的也是迭代延伸的思想,这里的bounding就不再是树的深度了,而是 f(n) 的值。

首先还是从s出发,,bounding的值就是f(s),接下来就是从s进行深度优先搜索,f() 值大约阈值的全部不管,没有找到的话就增大阈值,再进行DFS....直到最后找到最终的节点。

很明显,IDA*用深度优先搜索替代了Open List 和Close List, 减少了内存上的开销,也少了List维护的花费。虽然每次搜索都要从头开始,这看上去一次又一次去搜索同样的节点有点不合理,但是这个代价远远低于原版本中维护Open List和Close List.

边缘搜索A*

A*算法最大的性能问题就是Open List和Close List的维护,IDA*最大的问题就是无法记忆维护历史,会重复搜寻节点,一个新的寻路算法 - 边缘搜索A*,A*和IDA*的折中。

它维护了两个List,Now和Later来记录搜索的边缘点,同时用IDA*的思想来推进,具体看一下伪代码。

now - linked list of search nodes, list order determines order of evaluation
later - linked list of search nodes
root - start node
threshold = root‘s g()
push root into now

while now not empty
	for each node in now
		if node == goal
			stop
		if node‘s f() > threshold
			push node onto end of later
		else
			insert children of node into now behind node

		remove node from now and discard

	push later onto now, clear later
	set threshold = minimum g() found that is higher than current threshold

now中存放的是当先需要被评估的节点,later中存放的是下一次将要评估的节点。

这个过程以比较弱的排序来维护列表,并且以像IDA*的深度优先的方式来有效地扩展节点,如果一次完成遍历now之后没有找到目标,则增加threshold值,later列表变成now列表,搜索又从now列表的顶点开始。虽然搜索过程需要now和later列表的维护,却没有排序的开销,而且内存的消耗比A*少太多。

参考

Artificial Intelligence 3.7 - http://www.cs.ubc.ca/~poole/aibook/html/ArtInt_62.html

Iterative Deepening - http://www.comp.lancs.ac.uk/computing/research/aai-aied/people/paulb/old243prolog/subsection3_6_4.html

Game Programming Gems 3.7

时间: 2024-10-22 21:18:51

A*寻路算法的优化与改进的相关文章

算法:Astar寻路算法改进,双向A*寻路算法

早前写了一篇关于A*算法的文章:<算法:Astar寻路算法改进> 最近在写个js的UI框架,顺便实现了一个js版本的A*算法,与之前不同的是,该A*算法是个双向A*. 双向A*有什么好处呢? 我们知道,A*的时间复杂度是和节点数量以及起始点难度呈幂函数正相关的. 这个http://qiao.github.io/PathFinding.js/visual/该网址很好的演示了双向A*的效果,我们来看一看. 绿色表示起点,红色表示终点,灰色是墙面.稍浅的两种绿色分别代表open节点和close节点:

算法:Astar寻路算法改进

早前写了一篇<RCP:gef智能寻路算法(A star)> 出现了一点问题. 在AStar算法中,默认寻路起点和终点都是N x N的方格,但如果用在路由上,就会出现问题. 如果,需要连线的终点并不在方格的四角上,就产生了斜线.于是我们可以对终点附近的点重新做一点儿处理,源码如下所示: int size = points.size(); if (size < 3) return; points.removePoint(size - 1); Point pointN1 = points.ge

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

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

A*寻路算法的探寻与改良(三)

A*寻路算法的探寻与改良(三) by:田宇轩                                        第三分:这部分内容基于树.查找算法等对A*算法的执行效率进行了改良,想了解细化后的A*算法和变种A*算法内容的朋友们可以跳过这部分并阅读稍后更新的其他内容 3.1 回顾 在我的上一篇文章中,我们探讨了如何用编程实现A*算法,并给出了C语言的算法实现,这一章内容中我们主要研究如何提高A*算法的执行效率.抛开时间复杂度的复杂计算,我们大概可以知道,函数对数据的操作次数越少,达成

如何在Cocos2D游戏中实现A*寻路算法(八)

大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流之用,请勿进行商业用途.同时,转载时不要移除本申明.如产生任何纠纷,均与本博客所有人.发表该翻译稿之人无任何关系.谢谢合作! 就拿上图中左上角的情况举个栗子. 这只猫咪想要从原点(O)到左下角的对角线方块中去.如果在左边或底下(或全部都有)有墙壁并且测试穿过对角线将会切入一个墙角(或2个).所以左下

K-means聚类算法的三种改进(K-means++,ISODATA,Kernel K-means)介绍与对比

  一.概述 在本篇文章中将对四种聚类算法(K-means,K-means++,ISODATA和Kernel K-means)进行详细介绍,并利用数据集来真实地反映这四种算法之间的区别. 首先需要明确的是上述四种算法都属于"硬聚类"算法,即数据集中每一个样本都是被100%确定得分到某一个类别中.与之相对的"软聚类"可以理解为每个样本是以一定的概率被分到某一个类别中. 先简要阐述下上述四种算法之间的关系,已经了解过经典K-means算法的读者应该会有所体会.没有了解过

[聚类算法]K-means优缺点及其改进

[聚类算法]K-means优缺点及其改进 [转]:http://blog.csdn.net/u010536377/article/details/50884416 K-means聚类小述 大家接触的第一个聚类方法,十有八九都是K-means聚类啦.该算法十分容易理解,也很容易实现.其实几乎所有的机器学习和数据挖掘算法都有其优点和缺点.那么K-means的缺点是什么呢? 总结为下: (1)对于离群点和孤立点敏感: (2)k值选择; (3)初始聚类中心的选择: (4)只能发现球状簇. 对于这4点呢的

PHP树生成迷宫及A*自己主动寻路算法

PHP树生成迷宫及A*自己主动寻路算法 迷宫算法是採用树的深度遍历原理.这样生成的迷宫相当的细,并且死胡同数量相对较少! 随意两点之间都存在唯一的一条通路. 至于A*寻路算法是最大众化的一全自己主动寻路算法 完整代码已上传,http://download.csdn.net/detail/hello_katty/8885779 ,此处做些简单解释,还须要大家自己思考动手.废话不多说,贴上带代码 迷宫生成类: /** 生成迷宫类 * @date 2015-07-10 * @edit http://w

用简单直白的方式讲解A星寻路算法原理

很多游戏特别是rts,rpg类游戏,都需要用到寻路.寻路算法有深度优先搜索(DFS),广度优先搜索(BFS),A星算法等,而A星算法是一种具备启发性策略的算法,效率是几种算法中最高的,因此也成为游戏中最常用的寻路算法. 直入正题: 在游戏设计中,地图可以划分为若干大小相同的方块区域(方格),这些方格就是寻路的基本单元. 在确定了寻路的开始点,结束点的情况下,假定每个方块都有一个F值,该值代表了在当前路线下选择走该方块的代价.而A星寻路的思路很简单:从开始点,每走一步都选择代价最小的格子走,直到达