赞
踩
A ∗ A^* A∗( A s t a r A\ star A star)算法是一种启发式搜索算法,主要实现对图的路径搜索。 A ∗ A^* A∗算法基于 B F S BFS BFS(广度优先搜索),由于 B F S BFS BFS具有盲目性,会进行许多偏离最佳路径的搜索,故此 A ∗ A^* A∗算法主要目的就是克服 B F S BFS BFS的盲目性,在进行光度搜索时有目的的选择搜索结点。
在学习 A ∗ A^* A∗算法之前,首先需要引入评估函数 f ( n ) = h ( n ) + g ( n ) f(n)=h(n)+g(n) f(n)=h(n)+g(n),它用于评估搜索点 n n n的优先级。
其中, f ( n ) f(n) f(n)是搜索点 n n n的优先级, f ( n ) f(n) f(n)越小优先级越高。 h ( n ) h(n) h(n)表示从起点到点 n n n的已花费代价。 g ( n ) g(n) g(n)表示点 n n n到终点的估计代价。
B F S BFS BFS是广度优先搜索,他通常采用一个队列,每次从队首读入访问一个点,并把他连接的为访问点放入队尾,直到队列为空。 B F S BFS BFS的模板如下:
void BFS(int k){ queue<int> Q; Q.push(k);//将点k入队 visit[k]=1;//标记已访问k while(!Q.empty()){ int u=Q.front();Q.pop();//出队 visit[u]=1;//标记u已访问 if(u==end){//找到终点 //得到结果的相关操作; } for(int i=head[u];i;i=last[i]){//访问u连接的结点 int v=to[i];//v是u连接的结点编号 if(!visit[v]){ Q.push(v); } } } }
A ∗ A^* A∗算法所做的工作就是修改队列的逻辑,因为我们要按优先级访问,所以需要使用优先队列。在 C + + C++ C++当中,可以直接用 p r i o r i t y _ q u e u e priority\_queue priority_queue优先队列,存入顶点可以用 p a i r < p r i , n o d e > pair<pri,node> pair<pri,node>来存取, p r i pri pri表示优先级, n o d e node node表示顶点编号,因为 p a i r pair pair默认比较逻辑是按照第一个值来比较,所以第一个应该是优先级。
void Astar(int k){ typedef pair<int,int> pir; priority_queue<pir,vector<pir>,greater<pir> > Q;//因为优先队列默认是大根堆,所以要修改一下比较逻辑 Q.push(make_pair(0,k));//将点k入队,优先级0最高 visit[k]=1;//标记已访问k while(!Q.empty()){ int u=Q.front().first;Q.pop();//出堆 visit[u]=1;//标记u已访问 if(u==end){//找到终点 //得到结果的相关操作; } for(int i=head[u];i;i=last[i]){//访问u连接的结点 int v=to[i];//v是u连接的结点编号 if(!visit[v]){ Q.push(make_pair(f(v)+g(v),v));//v和v的评估入堆 } } } }
一般来说, h ( n ) h(n) h(n)评估起点到 n n n的距离可以通过搜索过程计算出来, g ( n ) g(n) g(n)到终点的距离可以通过反向 D i j k s t r a 、 S P F A Dijkstra、SPFA Dijkstra、SPFA等等单源最短路径算法作为参考值。更一般的,可以使用曼哈顿距离、对角距离、欧氏距离等等来评估。
部分游戏的寻路算法就是用了 A ∗ A^* A∗,除此之外, A ∗ A^* A∗还可以用来求解 k k k短路问题,当第 k k k次搜索找到终点时,即为 k k k短路。但在一般情况下, A ∗ A^* A∗只能找到较优解,而不一定是最优解。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。