【C++】A*算法

算法简介

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是广度优先搜索,他通常采用一个队列,每次从队首读入访问一个点,并把他连接的为访问点放入队尾,直到队列为空。 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

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 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) g ( n ) g(n) g(n)

一般来说, 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 DijkstraSPFA等等单源最短路径算法作为参考值。更一般的,可以使用曼哈顿距离、对角距离、欧氏距离等等来评估。

应用

部分游戏的寻路算法就是用了 A ∗ A^* A,除此之外, A ∗ A^* A还可以用来求解 k k k短路问题,当第 k k k次搜索找到终点时,即为 k k k短路。但在一般情况下, A ∗ A^* A只能找到较优解,而不一定是最优解。

你可能感兴趣的:(C/C++,算法,c++,数据结构)