启发式搜索 :A*算法详解

这篇具有很好参考价值的文章主要介绍了启发式搜索 :A*算法详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

A*算法

A*算法,(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法,也是解决许多搜索问题的有效算法。

算法中的距离估算值与实际值越接近,最终搜索速度越快。

回顾:BFS、Dijkstra

对于求两个点之间的最短路

普通的BFS是按层遍历的过程,以起点为中心,以到终点的最短路为半径的整个圆内的所有点都会被遍历到

Dijkstra是通过优先队列进行的优化,相当于一种贪心,正因为其本质是一种贪心,所以选择的永远是局部最优,也就是选择的是从起点到当前位置的距离的最小值的点来继续更新。如果开始的搜索中起始点到该点的代价很小,但在未来的搜索中,从该目标到终点的代价很大,就可能会花费很大的代价。也就是说优先队列优化的bfs缺乏对未来的估计。

A*算法-估价函数

A* 算法是一种启发式搜索,根据估价函数+当前代价作为优先队列的排序标准,相当于纵观历史与预见未来同时作用

估价函数指的是从当前点到终点的代价的一个估计值

估价函数的设计原则:估值必须比实际更优(估计代价<=实际代价)

  • 如果把好的状态估差了,那本来在最优解搜索路径上的状态被错误地估计了较大的代价,被压在堆中无法及时取出,从而导致非最优解搜索路径上的状态不断扩展,直至在目标状态上产生错误的答案把

  • 如果把坏的状态估好了,只要估价不大于未来实际代价,这个值总会比最优解更早地被取出,从而得到修正。最坏后果无非就是算的状态多了,跑得慢一些。

所以我们要选择一个好的估价函数,选择良好的估计函数可以使得A*算法的时间得到缩减,估价函数越接近真实代价,速度越快

当估价函数等于0,则退化成普通的优先队列版的bfs

例题:第K短路

思路:

it的最短路作为估价函数f(i)

优先队列就按照当前走过的路径的长度 + 估计函数最小的状态去扩展

#include <bits/stdc++.h>
using namespace std;

#define endl '\n'
#define inf 0x3f3f3f3f
#define mod7 1000000007
#define mod9 998244353
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define io ios::sync_with_stdio(false)
#define debug(a) cout << "Debuging...|" << #a << ": " << a << "\n";
typedef long long ll;
typedef pair <int,int> pii;
typedef pair<int, pii> piii;

#define MAX 300000 + 50
int n, m, k, x, y, z;
int s, t;

int tot;
int head[MAX];
int rhead[MAX];
struct ran{
    int to, nex, val;
}tr[MAX];
inline void add(int he[], int u, int v, int c){
    tr[++tot].to = v;
    tr[tot].val = c;
    tr[tot].nex = he[u];
    he[u] = tot;
}

int dis[MAX];
bool vis[MAX];
void dijkstra(int s){
    priority_queue<pii, vector<pii>, greater<pii>>q;
    mem(dis, inf);
    q.push(m_p(0, s));dis[s] = 0;
    while (!q.empty()) {
        int u = q.top().second;q.pop();
        if(vis[u])continue;
        vis[u] = 1;
        for(int i = rhead[u]; i; i = tr[i].nex){
            int v = tr[i].to;
            if(dis[v] > dis[u] + tr[i].val){
                dis[v] = dis[u] + tr[i].val;
                q.push(m_p(dis[v], v));
            }
        }
    }
}

int num[MAX];
void Astar(){
    priority_queue<piii, vector<piii>, greater<piii> >q;
    q.push(m_p(dis[s], m_p(0, s)));
    while (!q.empty()) {
        auto [d, u] = q.top().second;q.pop();
        ++num[u];
        if(num[t] == k){
            cout << d << endl;
            return;
        }
        if(num[u] > k)continue;
        for(int i = head[u]; i; i = tr[i].nex){
            int v = tr[i].to;
            q.push(m_p(dis[v] + d + tr[i].val, m_p(d + tr[i].val, v)));
        }
    }
    cout << -1 << endl;
}

void work(){
    cin >> n >> m;
    for(int i = 1; i <= m; ++i){
        cin >> x >> y >> z;
        add(head, x, y, z);
        add(rhead, y, x, z);
    }
    cin >> s >> t >> k;
    if(s == t)++k;
    dijkstra(t);
    Astar();
}


int main(){
    io;
    work();
    return 0;
}

经验之谈

对于有向图,则建反图求以终点为起点的最短路为估价函数

对于网格形式的图,有以下这些启发函数可以使用:文章来源地址https://www.toymoban.com/news/detail-403678.html

  • 如果图形中只允许朝上下左右四个方向移动,则可以使用曼哈顿距离。
    • 曼哈顿距离: ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ |x_1-x_2|+|y_1-y_2| x1x2+y1y2
  • 如果图形中允许朝八个方向移动,则可以使用对角距离。
    • 对角距离: 2 ∗ m i n ( ∣ x 1 − x 2 ∣ , ∣ y 1 − y 2 ∣ ) + ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ \sqrt{2}*min(|x_1-x_2|,|y_1-y_2|)+|x_1-x_2|+|y_1-y_2| 2 min(x1x2,y1y2)+x1x2+y1y2
  • 如果图形中允许朝任何方向移动,则可以使用欧几里得距离。
    • 欧几里得距离: ( x 1 − x 2 ) 2 + ( y 1 − y 2 ) 2 \sqrt{(x_1-x_2)^2+(y_1-y_2)^2} (x1x2)2+(y1y2)2

到了这里,关于启发式搜索 :A*算法详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 启发式算法之灰狼优化算法

    蚁群算法?秃鹰算法?布谷鸟算法?鱼群算法?猴群算法?这都是些啥? 这些算法听起来都很接地气,实际上也确实很接地气。它们都是学者通过观察动物们的行为得到的灵感,从而设计出来的精彩的算法。以动物命名的算法可远不止这些,比如还有蜂群算法、狼群算法、蝙

    2024年02月13日
    浏览(42)
  • 【启发式算法】灰狼优化算法【附python实现代码】

    写在前面: 首先感谢兄弟们的订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。 路虽远,行则将至;事虽难,做则必成。只要有愚公移山的志气、滴水穿石的毅力,脚踏实地,埋头苦干,积跬

    2024年02月16日
    浏览(35)
  • 元启发式算法库 MEALPY 初体验-遗传算法为例

    官网: MealPY官网 开源许可: (GPL) V3 MEALPY (MEta-heuristic ALgorithms in PYthon) 是一个提供最新自然启发式元启发算法的Python模块,它是最大的此类Python模块之一。这些算法模仿自然界中的成功过程,包括生物系统以及物理和化学过程。mealPy 的目标是免费向所有人分享元启发领域的知识

    2024年04月11日
    浏览(42)
  • 数学启发式

    优化求解器 | Gurobi 数学启发式算法:参数类型与案例实现 数学启发式算法 | 可行性泵 (Feasibility Pump)算法精讲:一份让您满意的【理论介绍+编程实现+数值实验】学习笔记(Python+Gurobi实现) 大佬到底是大佬!这些资料太适合我这种没基础的人了! 数学启发式(Mathematical Heurist

    2024年02月04日
    浏览(38)
  • 【图论】树上启发式合并

    本篇博客参考: Oi Wiki 树上启发式合并 算法学习笔记(86): 树上启发式合并 首先,什么是 启发式合并 ? 有人将其称为“优雅的暴力”,启发式合并就是在合并两个部分的时候,将内容少的部分合并至内容多的部分,减少合并的操作时间 树上启发式合并(dsu on tree) 可以被用

    2024年04月15日
    浏览(51)
  • 树上启发式合并(dsu on tree)

    dsu on tree dsu text{dsu} dsu 一般指 disjoint set union text{disjoint set union} disjoint set union ,即并查集。 dsu on tree text{dsu on tree} dsu on tree 指树上合并与查询操作,但它的实现和普通的并查集并无关联,两者的共同点仅仅在于都能合并集合和查询而已。 dsu on tree text{dsu on tree} d

    2024年02月16日
    浏览(41)
  • 【论文阅读】聚集多个启发式信号作为监督用于无监督作文自动评分

    本文提出一个新的无监督的AES方法ULRA,它不需要真实的作文分数标签进行训练; ULRA的核心思想是使用多个启发式的质量信号作为伪标准答案,然后通过学习这些质量信号的聚合来训练神经自动评分模型。 为了将这些不一致的质量信号聚合为一个统一的监督信号,我们将自动

    2024年02月16日
    浏览(39)
  • 【无码专区1】简单路径的第二大边权(启发式合并+最小生成树)

    只有std,没有自我实现,所以叫做无码专区 description 给一张无向图,多次询问,每次询问两个点之间所有简单路径(不重复经过点)中边权第二大(不是严格第二大)的权值的最小值。 数据范围: 1 0 5 10^5 1 0 5 级别 我的想法 前 50 % 50% 5 0 % 的数据 q , n ≤ 1 0 3 , m ≤ 2 × 1 0

    2024年02月08日
    浏览(36)
  • 如何进行测试分析与设计-HTSM启发式测试策略模型 | 京东云技术团队

    测试,没有分析与设计就失去了灵魂; 测试人员在编写用例之前,该如何进行测试分析与设计呢?上次在《测试的底层逻辑》中讲到了【输入输出测试模型】,还讲到了【2W+1H测试分析法】,但2W1H分析法是初步的分析方法,具体在测试中如何落地,还需要更细的设计。 今天

    2024年02月05日
    浏览(49)
  • Codeforces Round 890 (Div. 2) D. More Wrong(交互题 贪心/启发式 补写法)

    题目 t(t=100)组样例,长为n(n=2000)的序列 交互题,每次你可以询问一个区间[l,r]的逆序对数,代价是 要在的代价内问出最大元素的位置,输出其位置 思路来源 neal Codeforces Round 890 (Div. 2) supported by Constructor Institute D (交互+分治) 附加强 - 知乎 题解 赛中开题顺序大失败没看这个

    2024年02月14日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包