Astar算法

1.什么是Astar算法?

Astar算法是一种图形搜索算法,常用于寻路。它是个以广度优先搜索为基础,集Dijkstra算法与最佳优先(best fit)算法特点于一身的一种算法。

它通过下面这个函数来计算每个节点的优先级,然后选择优先级最高的节点作为下一个待遍历的节点。优先级函数:

其中:

1.g(n) 是节点n距离起点的代价。

2.h(n)是节点距离终点的预计代价,也就是A*算法的启发函数。

A*算法伪代码如下:

//使用open_set、close_set来表示待遍历和已遍历的节点集合

open_set = PriorityQueue()//使用优先队列,每次选取优先级最高的节点
open_set.put(start,0)//将起点加入open_set
close_set = {} //close_set,顺便记录节点距起点的代价
came_from = {} //记录节点的父节点
came_from[start] = None

while(!open_set.empty()))//当待遍历节点集合不为空时循环
{
    current = open_set.get()//取出优先级最高的节点
    
    if(current == goal)
    {
        //找到终点后,返回路径(此处省略)
        break
    } 
    
    
    for next in graph.neighbors(current)//遍历当前节点的邻近节点
    {
        new_cost = close_set[current] + graph.cost(current,next)//计算next节点的代价
        if(!close_set.contain(next) or new_cost < close_set[next])//如果next节点不在close_set中(未遍历过)或者有更小的代价
        {
            close_set[next] = new_cost //更新代价
            priority = new_cost + h(n) //使用g(n)和h(n)计算优先级
            open_set.put(next,priority)//将next节点加入open_set中
            came_from[next] = current //设置其父节点
        }
    }
}

 2.启发函数会影响A*算法的行为:

        1.在极端情况下,当启发函数h(n)始终为0,则由g(n)来决定节点的优先级,此时算法就退化成了Dijkstra算法。

        2.在另一个极端情况下,如果h(n)相较于g(n)大很多,则此时只有h(n)产生效果,这也就变成了最佳优先搜索。

        3.如果h(n)始终小于等于节点n到终点的代价,被称为可接受启发式的A*,则A*算法一定保证能够找到最短路径。但是当h(n)的值越小,算法遍历越多的节点,导致算法越慢。

        4.如果h(n)完全等于节点n到终点的代价,则A*算法将找到最佳路径并且速度很快。但是很难做到这一点,因为很难确切算出距离终点还有多远。

        5.如果h(n)的值比节点n到终点的代价要大,则A*算法不能保证找到最短路径,不过此时会很快。

        由上面这些信息我们可以知道,通过调节启发函数我们可以控制算法的速度和精确度。因为在一些情况,我们可能未必需要最短路径,而是希望能够尽快找到一个路径即可。这也是A*算法比较灵活的地方。

3.对网格形式的图,有以下这些启发函数可以使用:

1.如果图形中只允许朝上下左右四个方向移动,则可以使用曼哈顿距离(Manhattan distance)。

2.如果图形中允许朝八个方向移动,则可以使用对角距离。

3.如果图形中允许朝任意方向移动,则可以使用欧几里得距离。

曼哈顿距离:

        如果图形中只允许朝上下左右四个方向移动,则启发函数可以使用曼哈顿距离,它的计算方法如下图所示:

         计算曼哈顿距离的函数如下,这里的D是指两个相邻节点之间的移动代价,通常是一个固定的常数:

function heuristic(node)
    local dx = abs(node.x-goal.x)
    local dy = abs(node.y-goal.y)
    return D * (dx + dy)
end

对角距离:

        如果图形中允许斜着朝邻近的节点移动,则启发函数可以使用对角距离。它的计算方法如下:

         计算对角距离的函数如下,这里的D2指的是两个斜着相邻节点之间的移动代价。如果所有节点都正方形,则其值就是:

function heuristic(node)
    local dx = abs(node.x-goal.x)
    local dy = abs(node.y-goal.y)
    return D * (dx + dy) + (D2 - 2 * D) * min(dx,dy)
end

欧几里得距离:

        如果图形中允许朝任意方向移动,则可以使用欧几里得距离。

        欧几里得距离是指两个节点之间的直线距离,因此其计算方法也是我们比较熟悉的:

         其函数表示如下:

function heuristic(node) =
    local dx = abs(node.x-goal.x)
    local dy = abs(node.y-goal.y)
    return D * sqrt(dx * dx + dy * dy)
end

 4.算法变种

ARA*

        ARA*全称是Anytime Repairing A,也称为Anytime A

D*

Field D*

Block A*

### A*算法介绍 A* (A-star) 算法是一种用于解决最短路径问题的启发式搜索算法,在众多同类算法中最为常用[^1]。该算法不仅能够高效地找到两点之间的最优路径,还因其灵活性而被广泛应用于各种场景下的路径规划。 #### 原理概述 核心在于通过评估函数f(n)=g(n)+h(n),其中n代表当前节点;g(n)是从起点到此节点的实际成本;h(n)则是从这个节点到达目的地的一个估算值(也称为启发式函数)[^2]。为了使计算更加精确并加快收敛速度,通常会选择合适的启发方式来定义h(n)。 #### 数据结构设计 对于每一个可能成为路径一部分的位置都会创建一个`Node`对象表示它,并记录下三个重要属性:位置坐标、累计开销以及预估剩余路程长度。此外还包括指向父级节点的链接以便回溯最终路线图[^4]: ```cpp struct Point { int x, y; Point(int _x, int _y): x(_x), y(_y){} }; struct Node { Point point; double g, h, f; Node *parent; Node(Point pt, double costToStart, double estimatedCostToEnd, Node* prev = nullptr) : point(pt), g(costToStart), h(estimatedCostToEnd), f(g + h), parent(prev) {} }; ``` 这里采用欧氏距离作为两个相邻顶点间边权度量标准之一,即直线上两点间的直线距离。 #### 实现流程 - 初始化开放列表OpenList和关闭列表CloseList为空集; - 将初始状态加入OpenList; - 当OpenList不为空时循环执行以下操作直到找到目标或者无法继续探索为止: - 从未处理过的候选集中选取具有最小f值得元素node_current移至ClosedList; - 对于所有邻接未访问过的新结点new_node, 如果新结点不在OpenList也不在ClosedList,则将其添加入OpenList并将current设为其前驱; 若已经在OpenList里存在相同坐标的旧版本old_version且经由current前往更优(即新的g较小),则更新其前置关系及相应费用。 一旦达到终点或遍历结束仍未发现可行方案,则返回所获得的最佳路径或是报告失败消息。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值