A*算法深入

A*算法思想容易理解,但要想设计出好的A*算法,则必需要全面深入了解它。在本文章中接下来的内容中,将全面深入探讨该话题。如果对该算法还没有理解的话,则请先查阅上篇文章《A*算法入门》,然后再看该文章。

一:理论篇

探讨:估值函数

A*算法之所以效率高是因为它是启发式的搜索算法。它是在Dijkstra算法的基础上,增加了书籍网路信息的评估,也就是增加了约束条件,从而改变算法的走向 -------- 即:是带有目的性的往目标节点逼近,而不是你Dijkstra算法那样盲目搜索。因此,A*算法的执行效率高低在非常大的程度上是依赖于估值函数的,估值函数构造的越准确,则A*搜索的时间越短。

估值函数的主要任务是预估待搜索节点的重要程度。其定义为从初始节点经过当前节点到达目标节点的最小代价路径的代价估计值。公式:f(n) = g(n) + h(n),f(n)即为估值函数,g(n) 为初始节点到当前节点的已知代价,h(n) 为当前节点到目标节点的预估函数,其实就是所谓的启发函数。其实如果网路点确定的话,h(n)的值也是确定的,关键就是要看h(n)到底是选择什么样的构造函数。不同的h(n),其值肯定不同,从而影响到f(n)的值。

构造的启发函数h(n),不能与实际最短路径相差太远。差的越远,则A*算法的搜索就越接近BFS,特别地,当h(n) = 0时,就完全退化为BFS了。因此搜索的时间就越来越高。因此,如果启发函数能构造成与实际最短路径完全一样的话,则理论上解搜索速度是最快的。但实际中,这是不可能的,因为它只是预估函数。

在实际中,如果想要尽量快速,就要尽量将该函数构造的越接近实际最短路径,而要做到这点,则必需要参考更多的启发信息量。如:当前待考察节点与目标节点的“关系”或系统中的其他一些信息量,比如:经过该当前待考察节点到目标节点的权重等等。但如此一来h(n)的计算量也会随之增加,因此,这是一种权衡的诀择。下面介绍几种觉的启发函数。

探讨:常见的启发函数

以下假设当前待考察节点为n1(x1, y1),目标节点为n2(x2, y2)。

A:曼哈顿距离

曼哈顿距离其实是一种城市街区距离,即:类似城市街区那样,计算两个路口间的距离是按这两个路口坐标的水平差量与垂直差量的总和来算的。因此:h(n1) = abs(x2 - x1) + abs(y2 - y1)。曼哈顿距离计算公式经试验是较为适合街区类型地图的。

B:对角距离

如果地图允许往对角方向运动的话,则曼哈顿距离是需要考虑8个方向的。因此为简化计算,可以简单使用4个方向来代替。对角距离只取曼哈顿距离的其中差距较大的那个信息。因此:h(n1) = max(abs(x2 - x1), abs(y2 - y1))。

C:欧几里德距离

如果地图是允许往任意方向运动的话,则可以考虑使用两点间的直线距离。因此:h(n1) = sqrt(abs(x2 - x1)^2 + abs(y2 - y1)^2)。

在实际构造启发函数时,如果有可能还可以考虑待考察节点的朝向信息。即:考虑待考察节点(也就是当前节点)朝向是否与起始节点往目标节点朝向吻合。朝向越稳合,则说明该节点越应该被重视。因此,不妨可以为启发函数设定一个系数。节点的朝向越吻合,则系数越低;朝向越不吻合,则系数越高。这样启发函数的启发信息参考的就越多。

二:实现篇

探讨:开表、闭表

启发函数的不同构造,是在整体上影响着算法的路径选择走向,从而影响算法的整体性能。一旦启发函数明确后,则算法的整体走向是确定的,之后影响算法的效率问题就落在算法实现层面。这其中开表与闭表的设计就显的尤为重要,为何?(不明白为何的人,请再次查阅上一篇《A*算法入门》篇,直到看懂为止)。

开表在算法中的作用不单单只是为了存储待考察的节点,在整个算法动作过程中,需要频繁取出(开)表中f(n)值最小的那个,以及需要频繁确认当前节点的邻接节点是否已落在在开表中。而闭也也是需要频繁被查阅是否当前节点的邻接节点已经在闭表中。因此,开表、闭表的性能十分重要。此处只论开表,如果开表设计好了,自然了解如果设计闭表。

方案一:链表(不可取)

使用链表可以在存储上得到便利,而定位f(n)值最小节点时,效率奇低,因而绝对不可取。

方案二:平衡二叉搜索树(可取,综合性能很好,但还不是最好的)

如果应用该方案,则一般情况下会优先考虑rb-tree。该结构是被大量试验证明,其在插入、查找、删除方面性能都很高的一种数据结构,而且许多语言都有对它进行设计实现。

方案三:(小根)堆(可取,性能很好,但只限在定位或提取f(n)值最小节点方面)

在定位或提取f(n)值最小节点方面,堆方案绝对会比二叉搜索树来的高,但其在定位当前节点的邻接节点是否已在表中时,则只能遍历表数据,这方面性能就大不如方案二。

在实际中,个人还是更推荐堆方案。之前设计的C++版本的A*算法,采用的便是堆方案。在88 x 88无掩码地图格上,任意两点间的寻路耗时都不超过4ms。而且该实现版本是适用于任何类型地图的。(其实该版本还是有可优化的空间的,因为在估值函数方面,本人没有做任何优化。)

其实A*算法在存储开销上,也是需要重点注意的,不同的设计者,设计方案不同,效率肯定也不一样,此处不讨论。Ok,今天到此为止吧,有兴趣的同学,欢迎共同探讨。

时间: 2024-10-10 20:50:47

A*算法深入的相关文章

经典排序算法 - 冒泡排序Bubble sort

 原文出自于 http://www.cnblogs.com/kkun/archive/2011/11/23/bubble_sort.html 经典排序算法 - 冒泡排序Bubble sort 原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换, 这样一趟过去后,最大或最小的数字被交换到了最后一位, 然后再从头开始进行两两比较交换,直到倒数第二位时结束,其余类似看例子 例子为从小到大排序, 原始待排序数组| 6 | 2 | 4 | 1 | 5 | 9 | 第一趟排序(外循环) 第

转载:DenseNet算法详解

原文连接:http://blog.csdn.net/u014380165/article/details/75142664 参考连接:http://blog.csdn.net/u012938704/article/details/53468483 本文这里仅当学习笔记使用,具体细节建议前往原文细度. 论文:Densely Connected Convolutional Networks 论文链接:https://arxiv.org/pdf/1608.06993.pdf 代码的github链接:h

基于位置信息的聚类算法介绍及模型选择

百度百科 聚类:将物理或抽象对象的集合分成由类似的对象组成的多个类的过程被称为聚类.由聚类所生成的簇是一组数据对象的集合,这些对象与同一个簇中的对象彼此相似,与其他簇中的对象相异."物以类聚,人以群分",在自然科学和社会科学中,存在着大量的分类问题.聚类分析又称群分析,它是研究(样品或指标)分类问题的一种统计分析方法.聚类分析起源于分类学,但是聚类不等于分类.聚类与分类的不同在于,聚类所要求划分的类是未知的. 分类和聚类算法一直以来都是数据挖掘,机器学习领域的热门课题,因此产生了众多的

密码算法详解——AES

0 AES简介 美国国家标准技术研究所在2001年发布了高级加密标准(AES).AES是一个对称分组密码算法,旨在取代DES成为广泛使用的标准. 根据使用的密码长度,AES最常见的有3种方案,用以适应不同的场景要求,分别是AES-128.AES-192和AES-256.本文主要对AES-128进行介绍,另外两种的思路基本一样,只是轮数会适当增加. 1 算法流程 AES加解密的流程图如下: AES加密过程涉及到4种操作:字节替代(SubBytes).行移位(ShiftRows).列混淆(MixCo

矩阵乘法的Strassen算法详解

题目描述 请编程实现矩阵乘法,并考虑当矩阵规模较大时的优化方法. 思路分析 根据wikipedia上的介绍:两个矩阵的乘法仅当第一个矩阵B的列数和另一个矩阵A的行数相等时才能定义.如A是m×n矩阵和B是n×p矩阵,它们的乘积AB是一个m×p矩阵,它的一个元素其中 1 ≤ i ≤ m, 1 ≤ j ≤ p. 值得一提的是,矩阵乘法满足结合律和分配率,但并不满足交换律,如下图所示的这个例子,两个矩阵交换相乘后,结果变了: 下面咱们来具体解决这个矩阵相乘的问题. 解法一.暴力解法 其实,通过前面的分析

关于SVM数学细节逻辑的个人理解(三) :SMO算法理解

第三部分:SMO算法的个人理解 接下来的这部分我觉得是最难理解的?而且计算也是最难得,就是SMO算法. SMO算法就是帮助我们求解: s.t.   这个优化问题的. 虽然这个优化问题只剩下了α这一个变量,但是别忘了α是一个向量,有m个αi等着我们去优化,所以还是很麻烦,所以大神提出了SMO算法来解决这个优化问题. 关于SMO最好的资料还是论文<Sequential Minimal Optimization A Fast Algorithm for Training Support Vector

基于Spark MLlib平台的协同过滤算法---电影推荐系统

基于Spark MLlib平台的协同过滤算法---电影推荐系统 又好一阵子没有写文章了,阿弥陀佛...最近项目中要做理财推荐,所以,回过头来回顾一下协同过滤算法在推荐系统中的应用. 说到推荐系统,大家可能立马会想到协同过滤算法.本文基于Spark MLlib平台实现一个向用户推荐电影的简单应用.其中,主要包括三部分内容: 协同过滤算法概述 基于模型的协同过滤应用---电影推荐 实时推荐架构分析     一.协同过滤算法概述 本人对算法的研究,目前还不是很深入,这里简单的介绍下其工作原理. 通常,

算法 希尔排序

希尔排序 Shell Sort 介绍: 希尔排序(Shell Sort)也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本. 该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个"增量"的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序.因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率比直接插入排序有较大提高. 执行流程: 首先

算法 排序NB二人组 堆排序 归并排序

参考博客:基于python的七种经典排序算法     常用排序算法总结(一) 序前传 - 树与二叉树 树是一种很常见的非线性的数据结构,称为树形结构,简称树.所谓数据结构就是一组数据的集合连同它们的储存关系和对它们的操作方法.树形结构就像自然界的一颗树的构造一样,有一个根和若干个树枝和树叶.根或主干是第一层的,从主干长出的分枝是第二层的,一层一层直到最后,末端的没有分支的结点叫做叶子,所以树形结构是一个层次结构.在<数据结构>中,则用人类的血统关系来命名,一个结点的分枝叫做该结点的"

【机器学习实战】第2章 K-近邻算法(k-NearestNeighbor,KNN)

第2章 k-近邻算法 <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=default"></script> KNN 概述 k-近邻(kNN, k-NearestNeighbor)算法主要是用来进行分类的. KNN 场景 电影可以按照题材分类,那么如何区分 动作片 和 爱情片 呢? 动作片:打斗次数更多 爱情片