A*算法心得

A*算法或者A-star算法,是基于dijsktra最短路算法进行的一种改进,对于基本上没有接触过此类算法的初学者,上手是不太容易的,而网上大部分中文资料较为简单,而且用的术语太多,比如启发式函数,而大部份资料主要是英文的,比如mit的pathfinding using A*,以下是我对网上英文资料的提炼,希望能将这个算法描述的浅显易懂。

首先介绍BFS(breadth first search)广度优先搜索

// Simple bfs
structure node
    position pos
    node *parent
end

function bfs(node start_position)
    add start_position to the queue
    while the queue is not empty
        pop a node off the queue, call it "item"
        color item on the graph // make sure we don't search it again
        generate the 8 successors to item
        set the parent of each successor to "item" // this is so we can backtrack our final solution
        for each successor
            if the successor is the goal node, end the search
            else, push it to the back of the queue // So we can search this node
        end
    end

    if we have a goal node, look at its ancestry to find the path (node->parent->parent->parent..., etc)
    if not, the queue was empty and we didn't find a path :^\
end

C++实现代码如下图

void BFS(graph g,node v)
{
    queue Q;
    Q.initial();
    visit(v);
    visited[v]=true;
    Q.in(v);
    while(!Q.isempty())
    {
        v=Q.out();
        w=Q.firstadj(g,v);
        while(w!=0)
        {
            visit(w);
            Q.in(w);
            visited[w]=true;
            w=nextadj(g,v,w);
        }
    }
}

有了这些为铺垫后,下面隆重推出A*算法,它作为一个有效的寻路算法被广泛应用在游戏中,我们可以看出使用BFS和DFS算法时是无目的的,因此也是耗费巨大的,而A*算法可以使损耗较小,也就是说,不费多少力气,不需要遍历每个节点,而是有目的性的找到最佳路径,那么最佳路径怎么找呢?
首先,我们先定义一个损失函数,用来计算一个结点的消耗

f=g+h

那么g和h分别是啥呢?
g代表从起点到当前结点已算出的确定路程,h代表我们猜从当前结点到终点要多远,比如我们可以在坐标轴中记录两点xy坐标之差的平方和再开根号,就是两点之间的直线距离,这个就是他们所说的启发式搜索
首先创建结点结构体

struct node {
    node *parent; //用来保存其父节点
    int x, y; //记录该节点位置
    float f, g, h; //分别对应上面函数的各个东西
}
    //A*
    初始化开启列表;
    初始化关闭列表;
    将起点放入开启列表中;
    while(开启列表非空)
        找到在开启列表上f最小的结点,记为q;
        找到q的周围子节点,设其父节点为q;
        for(q的每个子节点p)
            if(p是终点)
                停止搜索;
                p.g=q.g+qp之间距离;
                p.h=p距离终点的估测距离;
                p.f=p.g+p.h;
            if(p在开启列表中,已经保存的f值小于当前值||p在关闭列表中)
                跳过该结点;
            else 将该节点修改或加入开启列表中;
        end;
        将q加入到关闭列表中
    end;    

猜你喜欢

转载自blog.csdn.net/swordcloak/article/details/79052609