启发式搜索: A*算法

  • 回顾: 优先队列BFS、最短路
  • A*算法 – 估价函数
    • 为什么?
  • A*算法
  • 实战

回顾: 优先队列BFS、最短路

普通BFS:按层扩展
优先队列BFS:每次从队列中取出当前代价最小的状态进行扩展

优先队列BFS的局限性:
一个状态的当前代价最小,只能说明从起始状态到该状态的代价很小,而在未来的搜索中,从该状态到目标状态可能会花费很大的代价。反之亦然。当前代价较大,也许未来代价较小,总代价反而更优。优先队列BFS缺少对未来的预估。

A*算法 – 估价函数

A*算法是一种启发式搜索(Heuristically Search)算法

A*算法的关键是设计一个估价函数:

  • 以任意“状态”为输入,计算出从该状态到目标状态所需代价的估计值
  • 在搜索中,维护一个堆(优先队列),优先选择“当前代价+未来估价”最小的状态进行扩展

估价函数的设计原则:估值必须比实际更优(估计代价≤未来实际代价)
只要保证上述原则,当目标状态第一次从堆中被取出时,就得到了最优解

为什么?

把好状态估差的后果:
本来在最优解搜索路径上的状态被错误地估计了较大的代价,被压在堆中无法取出,从而导致非最优解搜索路径上的状态不断扩展,直至在目标状态上产生错误的答案
把坏状态估好的后果:
只要估价不大于未来实际代价,这个值总会比最优解更早地被取出,从而得到修正。最坏后果无非就是算的状态多了,跑得慢一些。

否决一个正确idea vs 多看一个垃圾idea

A*算法

A*和优先队列BFS的区别就是:考虑优先级的时候有没有加上未来估价

估价越精准(接近但不超过未来实际代价),A*算法越快
估价等于0,就退化为了优先队列BFS

A*算法的关键:开动脑筋,设计优秀的估价函数(必须要乐观估计,但也要尽量精准)

例如:求第K短路,把当前结点到终点的最短路作为估价函数(最短≤K短)
优先选择“当前走过的路径长度+估价函数”最小的状态扩展

实战

773.滑动谜题
https://leetcode.cn/problems/sliding-puzzle/

class Solution {public:int slidingPuzzle(vector<vector<int>>& board) {string start = zip(board);string target = zip({{1, 2, 3}, {4, 5, 0}});//q.push(start);q.push({-evaluate(start), start});depth[start] = 0;while (!q.empty()) {string s = q.top().second;q.pop();int pos = findZeroIndex(s);if (pos >= 3) expand(s, pos, pos - 3);if (pos <= 2) expand(s, pos, pos + 3);if (pos % 3 != 0) expand(s, pos, pos - 1);if (pos % 3 != 2) expand(s, pos, pos + 1);if (depth.find(target) != depth.end()) return depth[target];}return -1;}private:int evaluate(string &s) {int now[6];for (int i = 0; i < 6; i++) {if (s[i] != '0')now[s[i] - '0'] = i;}int target[6] = {0 ,0 ,1, 2, 3, 4};int ans = 0;for (int digit = 1; digit <= 5; digit++) {int nowx = now[digit] / 3;int nowy = now[digit] % 3;int targetx = target[digit] / 3;int targety = target[digit] % 3;ans += abs(nowx - targetx) + abs(nowy - targety);}return ans;}void expand(string& s, int pos, int other) {string ns = s;swap(ns[pos] , ns[other]);if (depth.find(ns) != depth.end()) return;depth[ns] = depth[s] + 1;q.push({ - depth[ns] - evaluate(ns), ns});//q.push(ns);}string zip(const vector<vector<int>>& board) {string res;for (int i = 0; i < 2; i++) {for (int j = 0; j < 3; j++) {res += '0' + board[i][j];}}return res;}int findZeroIndex(string& s) {for (int i = 0; i < 6; i++) if (s[i] == '0') return i;return -1;}//queue<string> q;priority_queue<pair<int, string>> q;unordered_map<string, int> depth;
};

选做题
八数码
https://www.acwing.com/problem/content/847/
https://www.acwing.com/problem/content/181/

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习

启发式搜索: A*算法相关推荐

  1. poj 2449 Remmarguts' Date 启发式搜索 A*算法

    做这个题算是学了学spfa算法,一开始感觉spfa和dij好像:dij找最小点松弛,spfa就是一个一个的松弛,松到不能松. 求S到T的第K短路 思路:这个算法的思路是从源点S优雅的暴力跑bfs,用优 ...

  2. 搜索 —— 启发式搜索 —— A* 算法

    [概述] A*(A-Star)算法是一种在静态路网中,求解最短路的最有效的直接搜索方法,也是解决许多搜索问题的有效算法之一. A* 算法实际上是对 Dijkstra 算法的优化后得到的,关于 Dijk ...

  3. 启发式搜索 A*算法的OC 实现

    前两天重新学习了下A*算法,上次学习A*算法已经是5年前了,看到网上铺天盖地的A*算法都是C.C++等等其他语言的,就是没有OC 的,所以抽空写了一份.今天太晚了就不说明A*算法的细节了,大家如果想学 ...

  4. 启发式搜索A*算法【引入及思想】

    算法介绍 A*(念做:A Star)算法是一种很常用的路径查找和图形遍历算法.它有较好的性能和准确度. A*算法最初发表于1968年,由Stanford研究院的Peter Hart, Nils Nil ...

  5. 路径规划之 A* 算法

    算法介绍 A*(念做:A Star)算法是一种很常用的路径查找和图形遍历算法.它有较好的性能和准确度.本文在讲解算法的同时也会提供Python语言的代码实现,并会借助matplotlib库动态的展示算 ...

  6. 15数码 java_A*算法求解15数码问题

    目录 一.问题描述 二.算法简介 三.算法步骤 四.评估函数 五.参考资料 六.源代码(Java实现) 一.问题描述 利用A*算法进行表1到表2的转换,要求空白块移动次数最少. 转换规则为:空白块只可 ...

  7. 寻路之 A* 搜寻算法

    最近做到一道题,题目如下: 有 A.B 两点,中间有一堆障碍物,求出A点到B的可行的路径,写出一个 DEMO 并可用任何语言实现(要求可以任意设置 A.B 点和障碍物的位置,需要做UI). 首先,理解 ...

  8. A-star 算法原理分析

    搜索算法 图论中,应用最广泛的就是搜索算法了,比如,深度优先搜索.广度优先搜索等.在介绍 Dijkstra 算法那篇中,除了深度优先.广度优先这种暴力搜索算法,还有一些最短路算法也可以求得最短路径,并 ...

  9. 路径规划—— A* 算法

    参考原文:路径规划之 A* 算法 (weibo.com) A*(念做:A Star)算法是一种很常用的路径查找和图形遍历算法.它有较好的性能和准确度. 本... 路径规划之 A* 算法 A*(念做:A ...

最新文章

  1. 01背包【动态规划】
  2. 安卓开发日记(1) - 安装 Android 开发环境和 first app
  3. 信息系统项目管理师-第5章:项目范围管理-重点汇总
  4. Hadoop:eclipse配置hadoop-eclipse-plugin(版本hadoop2.7.3)
  5. python需要配置环境变量吗_教你手动设置python环境变量
  6. 截取字符串,但要保证汉字不被截取半个
  7. 提问的智慧 如何得到好的帮助(转)
  8. Android之MediaProjectionManager实现手机截屏总结
  9. php base64安全吗,php base64
  10. matlab色度椭圆,matlab画色度图
  11. 爬取哔哩哔哩单个视频
  12. 这可能是最简单,精炼,有效的magisk 安装教程,附boot.img 提取方法
  13. boost 进程间通信-share memery传递字符串
  14. shuipfcms二次开发之图片上传
  15. Cadence Allegro如何导出与导入规则
  16. 2022年5月编程语言排行榜:C# 获得最多排名积分
  17. 禾川Q0 PLC ModbusRTU通讯
  18. 第13节 IIS之WEB服务器部署及网站发布——以win2003为例
  19. py使用polar绘制霍兰德职业测试雷达图
  20. [转载备用]微信直播的优势及微信直播搭建过程(点赞:主播妹子有点靓哦)

热门文章

  1. mysql数据库误删且未持久化_MySQL恢复误删数据解决方案
  2. 【Argoverse 1 Motion Forecasting Dataset】轨迹预测数据集简介
  3. fedora 下常用软件安装
  4. Notification 加入本地的声音文件
  5. 【网络通信】WSAStartup()函数,MAKEWORD的使用
  6. C语言实现获取文件后缀、修改后缀
  7. (4) STM32 AS608指纹识别模块测试代码
  8. 7-7 六度空间 (30 point(s))
  9. win左下角搜索框打不开,没有响应解决办法
  10. 学会OpenStack之核心Nova服务一篇就够了!!!