寻路算法之A*算法

A*算法是用于寻找两点之间的最短路径,同时它也是一种静态路网中求解最短路最有效的直搜索方法,公式f(n)=h(n)+g(n)给出了邻居节点到目标节点所需要的总消耗成本,h(n)是当前节点到该邻居节点的所消耗的成本,g(n)是该邻居节点到目标节点的估计消耗成本,比较常用的估计方法是欧几里得方法和曼哈顿方法。

A*算法首先要准备两个列表,一个开启列表,一个关闭列表,开启列表存储还未走的节点(但不是一开始就把所有节点加入开启列表),关闭列表存储走过的节点,将起始节点加入到开启列表,在开启列表不为空时,取出开启列表中最小消耗成本的节点,判断是否是目标节点,是就直接结束A*,取得它的周围邻居节点(通常是8个),判断邻居节点是否在关闭列表中,在关闭列表中,不做处理,不在关闭列表中,再判断是否在开启列表中,若已在开启列表中,计算它的f(n),是否比以前的f(n)小,小就更新它的f(n)并将它的父节点设为当前节点。大的话就不做处理,若不在开启列表中,计算它的f(n),更新f(n)将父节点设为当前节点。处理完它的周围邻居节点后,一轮循环结束,再移除开启列表中的当前节点,放在关闭列表中,因为已经走过这个节点。然后在开启列表不为空时继续上述循环,直到找到目标节点,或者找遍所有节点都找不到目标节点。C++代码如下(相关函数并未实现,视实际情况而定):

 1 typedef struct node
 2 {
 3 float currentCost;//h(n)
 4 float toTalCost;//f(n)
 5 node * parent;//父节点
 6 }Node;
 7 Vector<Node>  OpenList;//开启列表
 8 Vector<Node>  CloseList;//关闭列表
 9
10 Node  AStar(Node start,Node Goal){
11   OpenList.Add(start);
12   while(OpenList.Length!=0)
13 {
14       Node* minNode=  OpenLIst.Min();//Min()选出最小消耗成本节点
15       if(minNode == Goal)
16 {
17 return minNode;
18 }
19        Vector<Node> Neighbors;//邻居列表
20          GetNeighBors(Neighbors,minNode);/*得到最小消耗成本节点的周围邻居节点*/
21            for(int i=0;i<NeighBors.Count;i++)
22 {
23          if(Neighbors[i].obstacle)//如果邻居节点被标志障碍物,跳过。
24 {
25 continue;/*也可以在GetNeighBors函数里进行处理,障碍物节点不加入邻居列表*/
26 }
27 if(CloseList.Contain(Neighbors[i]))//节点已经走过不作处理
28 continue;
29 float currentCost=CacluateDistance(minNode,Neighbors[i])+minNode.currentCost;
30 float totalCost = currentCost+CacluateDistance(Neighbors[i],Goal);
31 if(OpenList.Cotain(Neighbors[i]))//如果开启列表包含该邻居节点
32 {
33
34 if(totalCost<Neighbors[i].totalCost)
35 {
36 Neighbors[i].totalCost=totalCost;
37 Neighbors[i].currentCost =currentCost;
38 Neighbors[i].parent=minNode;
39 }
40 }
41 else
42 {
43 Neighbors[i].totalCost=totalCost;
44 Neighbors[i].currentCost =currentCost;
45 Neighbors[i].parent=minNode;
46 }
47 }
48 OpenList.Remove(minNode);
49 CloseList.Add(minNode);
50  }
51 return NULL;//找不到目标节点,返回空
52 }

若成功返回一个节点,那么可以不断往回迭代父节点得到一条逆向的最短路径。A*的思想是为每个节点都估价消耗成本(沿当前所走的路径到目标节点的消耗成本),选择最小消耗成本的节点优先计算,就使节点搜索沿目标节点那边搜索,也被称之为启发式搜索。而开启列表得到最小的消耗成本节点或添加节点,应该用二叉堆(最小堆)插入,这样取最小节点时间复杂度为O(1),添加节点时间复杂度为O(log(n)),比另一种遍历取节点O(n),加节点O(1)好一些。

时间: 2024-10-21 17:02:54

寻路算法之A*算法的相关文章

图解NavMesh寻路中的漏斗算法

NavMesh是广泛使用的一种寻路技术,将地图中可走的部分生成连续的多边形/三角形网格,寻路在网格中进行,主要包含两步:1.根据网格的邻接信息构造图,使用A*之类的寻路算法计算出从起点到重点需要走过的多边形/三角形集合:2.使用漏斗算法/拉绳子算法,将多边形列表转换为一条最优的路店.本文主要讲一下对于三角形列表的漏斗算法原理. 诸位读者如果搜索过网络,会发现有一年GDC有人讲了这个算法,也有几篇博客翻译了这个GDC的演讲slides,但多半都是仅仅翻译一遍slides的水平,没有真的把算法说明白

一步一步写算法(之 算法总结)

原文:一步一步写算法(之 算法总结) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 自10月初编写算法系列的博客以来,陆陆续续以来写了几十篇.按照计划,还有三个部分的内容没有介绍,主要是(Dijkstra算法.二叉平衡树.红黑树).这部分会在后面的博客补充完整.这里主要是做一个总结,有兴趣的朋友可以好好看看,欢迎大家提出宝贵意见. (1) 排序算法 快速排序 合并排序 堆排序 选择排序 基数排序 冒泡排序 插入排序 希尔排序 链表排序

条件随机场(CRF) - 4 - 学习方法和预测算法(维特比算法)

声明: 1,本篇为个人对<2012.李航.统计学习方法.pdf>的学习总结,不得用作商用,欢迎转载,但请注明出处(即:本帖地址). 2,由于本人在学习初始时有很多数学知识都已忘记,所以为了弄懂其中的内容查阅了很多资料,所以里面应该会有引用其他帖子的小部分内容,如果原作者看到可以私信我,我会将您的帖子的地址付到下面. 3,如果有内容错误或不准确欢迎大家指正. 4,如果能帮到你,那真是太好了. 学习方法 条件随机场模型实际上是定义在时序数据上的对数线性模型,其学习方法包括极大似然估计和正则化的极大

[数据挖掘] - 聚类算法:K-means算法理解及SparkCore实现

聚类算法是机器学习中的一大重要算法,也是我们掌握机器学习的必须算法,下面对聚类算法中的K-means算法做一个简单的描述: 一.概述 K-means算法属于聚类算法中的直接聚类算法.给定一个对象(或记录)的集合,将这些对象划分为多个组或者“聚簇”,从而使同组内的对象间比较相似而不同组对象间差异比较大:换言之,聚类算法就是将相似的对象放到同一个聚簇中,而将不相似的对象放到不同的聚簇中.由于在聚类过程中不使用到类别标签,所以相似性的概念要基于对象的属性进行定义.应用不同则相似性规则和聚类算法一般不太

【强连通分量】tarjan算法及kosaraju算法+例题

阅读前请确保自己知道强连通分量是什么,本文不做赘述. Tarjan算法 一.算法简介 Tarjan算法是一种由Robert Tarjan提出的求有向图强连通分量的时间复杂度为O(n)的算法. 首先我们要知道两个概念:时间戳(DFN),节点能追溯到的最早的栈中节点的时间戳(LOW).顾名思义,DFN就是在搜索中某一节点被遍历到的次序号(dfs_num),LOW就是某一节点在栈中能追溯到的最早的父亲节点的搜索次序号. Tarjan算法是基于深度优先搜索的算法.在搜索过程中把没有Tarjan过的点入栈

BF算法与KMP算法

BF(Brute Force)算法是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配,若相等,则继续比较S的第二个字符和 T的第二个字符:若不相等,则比较S的第二个字符和T的第一个字符,依次比较下去,直到得出最后的匹配结果. BF算法实现: 1 int BF(char S[],char T[],int pos) 2 {//c从第pos位开始搜索匹配 3 int i=pos,j=0; 4 while(S[i+j]!='\0'&&T[j]!='\0')

排序算法之归并算法

/* 本例拟在实现排序算法的归并算法,归并算法遵循分治法的思想 归并算法: 归并算法主要用来合并两个已经排好序的序列.用Merge(A,p,q,r)来实现合并, 其中A代表数组,A[p,q]和A[q+1,r]A的两个子数组,且两个数组都已经排好序,归并算法 就是将这两个子数组合并成一个排好序的数组并替代当前的数组A[p,r]. */ public class Merge { public static void main(String[] args) { int[] a = {1,2,3,4,5

最小生成树(prim算法,Kruskal算法)c++实现

1.生成树的概念 连通图G的一个子图如果是一棵包含G的所有顶点的树,则该子图称为G的生成树. 生成树是连通图的极小连通子图.所谓极小是指:若在树中任意增加一条边,则将出现一个回路:若去掉一条边,将会使之变成非连通图. 生成树各边的权值总和称为生成树的权.权最小的生成树称为最小生成树. 2.最小生成树的性质用哲学的观点来说,每个事物都有自己特有的性质,那么图的最小生成树也是不例外的.按照生成树的定义,n 个顶点的连通网络的生成树有 n 个顶点.n-1 条边. 3.构造最小生成树,要解决以下两个问题

五大算法思想—贪心算法

贪心法理解 贪心法在解决问题的策略上目光短浅,只根据当前已有的信息就做出选择,而且一旦做出了选择,不管将来有什么结果,这个选择都不会改变.换言之,贪心法并不是从整体最优考虑,它所做出的选择只是在某种意义上的局部最优. 一句话:不求最优,只求可行解. 判断贪心法 对于一个具体的问题,怎么知道是否可用贪心算法解此问题,以及能否得到问题的最优解? 我们可以根据贪心法的2个重要的性质去证明:贪心选择性质和最优子结构性质. 1.贪心选择性质 什么叫贪心选择?从字义上就是贪心也就是目光短线,贪图眼前利益,在

行为识别笔记:improved dense trajectories算法(iDT算法)(转载)

iDT算法是行为识别领域中非常经典的一种算法,在深度学习应用于该领域前也是效果最好的算法.由INRIA的IEAR实验室于2013年发表于ICCV.目前基于深度学习的行为识别算法效果已经超过了iDT算法,但与iDT的结果做ensemble总还是能获得一些提升.所以这几年好多论文的最优效果都是"Our method+iDT"的形式. 此前由于项目原因,对iDT算法进行了很多研究和实验,故此处对其核心思路与一些实施的细节进行总结,方便后续回顾,也希望能够在此过程中获得一些新的启发. 介绍的内