A*算法在求最短路上的应用

在学习A*算法之前,首先回忆一下一个非常经典的单源最短路算法Dijkstra

1)维护一个表dist,储存当前求出的各点到S的距离

2)取出dist表中的最小值(显然这个过程是可以用堆优化的),并用该最小值对其他各点的dist值做松弛更新

3)重复2)过程,直到取出的最小值对应节点为T

这里其实无形中也用到了接下来即将讲到的open表和close表的概念

open表储存的是待扩展的点,一定程度上对应Dijkstra中的list

close表中储存的是已经扩展过的点,以防出现重复

那么接下来谈谈A*算法在Dijkstra算法的基础上做了什么

让我们回忆一下,多源最短路算法求出来的结果是什么,其实远远超出了我们的所需,我们最终得到的dist,是S到所有点的最短路距离。

然而当我们只需要S到T的最短路时,我们为什么需要去扩展那些我们没有必要扩展的点,哪怕它对应当前最小的dist?最小的dist又不一定会对S到T的最短路求解有必然的帮助。

所以我们需要引入一个评估函数

            f(p)=h(p)+g(p)

其中, g(p)表示S到p的实际最短距离,h(p)表示p到T的估计距离

g(p)是容易解决的,因为当你对p开始进行评估时,说明它的dist是当前最小,毫无疑问它当前的dist就是g(p)

h(p)取决于问题设定,视情况而定,一般设为p到T的曼哈顿距离或欧几里得距离(栅格化地图中前者更常用)

当你发现,f(p)甚至比当前T的dist还要大,那么根本没有必要对p进行拓展。假装自己扩展过了,将p打入close表的冷宫吧!

这里有一个前提,h(p)估算出的距离必须小于或等于p到T的实际最短距离,这一点比较显然,却是A*算法优化的基础(其实就是一个很基本的搜索剪枝的思想)

先给出A*的流程

1)将起点S放入open表中

2)对open表中dist最小的相邻节点进行评估,评估不合格则直接放入close表(孩子你没救了,洗洗睡吧

  否则进行拓展,将该点放入open表待扩展(少侠有前途,我钦点看好你

  扩展以后的点,也放入close表(该干的都干了,可以卸甲归田了

3)close表中出现了T!那啥也别说了,算法结束

如果需要记录路径的话,只要记录一下某个点是从哪个点扩展而来的,记录一下父节点即可。

最后思考一下为什么A*算法中这么强调open表

因为A*算法利用评估函数力求缩减扩展的次数,但Dijkstra一开始就是冲着把所有点扩展一遍去的,因而不需要open表(因为它的open表默认包含了所有点)

但A*则是在评估以后再判断是否放入open表中扩展,这就是优化所在。

时间: 2024-08-24 11:51:27

A*算法在求最短路上的应用的相关文章

Crowd Control(输出不在最大值最小化的最短路上的边)

题意: 就是求完最大值最小化  然后输出在这条最大值最小化的最短路上的点的不在最短路上的边,emm.... 解析: 很明显,先套spfa最大值最小化模板,emm... 在更新d的时候 用一个pre去记录父结点 跑完spfa后用dfs把这条最短路上所有经过的点找出来 放在vector里,用数组也行,这不是好用嘛..emm.. 然后在跑一次dfs(其实两个循环就能解决..我怕超时..所以用了dfs..然而可能没啥区别..不会算复杂度的我瑟瑟发抖) 遍历这些点  在遍历每个点的同时去遍历所有的边 找出

1103: 零起点学算法10——求圆柱体的表面积

1103: 零起点学算法10--求圆柱体的表面积 Time Limit: 1 Sec  Memory Limit: 128 MB   64bit IO Format: %lldSubmitted: 11616  Accepted: 1956[Submit][Status][Web Board] Description 很简单的问题,求圆柱体的表面积 Input 多组测试数据,每组输入底面半径r和高h Output 每组输出圆柱体的表面积,保留3位小数 Sample Input 3.5 9 Sam

1104: 零起点学算法11——求梯形面积

1104: 零起点学算法11--求梯形面积 Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 6473  Accepted: 1875[Submit][Status][Web Board] Description 水题 Input 输入3个浮点数,分别表示上底.下底和高,中间用逗号隔开(题目包含多组数据) Output 输出梯形的面积,保留2位小数 Sample Input 2,4,5 Sample

1140: 零起点学算法47——求平均值

1140: 零起点学算法47--求平均值 Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 1408  Accepted: 873[Submit][Status][Web Board] Description 输入一些整数,求平均值 Input 多组测试数据 首先输入1个整数n表示测试组数 然后每行首先输入1个整数m,再输入m个整数 Output 对于每组测试数据输出1行,内容为m个整数的平均值,保留

1138: 零起点学算法45——求最大值

1138: 零起点学算法45--求最大值 Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 1691  Accepted: 879[Submit][Status][Web Board] Description 输入一些整数,求最大值 Input 多组测试数据 首先输入1个整数n表示测试组数 然后每行首先输入1个整数m,再输入m个整数 Output 对于每组测试数据输出1行,内容为m个整数的最大值 Sa

1139: 零起点学算法46——求最小值

1139: 零起点学算法46--求最小值 Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 1399  Accepted: 879[Submit][Status][Web Board] Description 输入一些整数,求最小值 Input 多组测试数据 首先输入1个整数n表示测试组数 然后每行首先输入1个整数m,再输入m个整数 Output 对于每组测试数据输出1行,内容为m个整数的最小值 Sa

一个文件中有40亿个整数,每个整数为四个字节,内存为1GB,写出一个算法:求出这个文件里的整数里不包含的一个整数

4个字节表示的整数,总共只有2^32约等于4G个可能.为了简单起见,可以假设都是无符号整数.分配500MB内存,每一bit代表一个整数,刚好可以表示完4个字节的整数,初始值为0.基本思想每读入一个数,就把它对应的bit位置为1,处理完40G个数后,对500M的内存遍历,找出一个bit为0的位,输出对应的整数就是未出现的.算法流程:1)分配500MB内存buf,初始化为02)unsigned int x=0x1;  for each int j in file  buf=buf|x<<j;  e

1130: 零起点学算法37——求阶乘

1130: 零起点学算法37--求阶乘 Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 2109  Accepted: 1328[Submit][Status][Web Board] Description 输入一个正整数n,计算它的阶乘 Input 输入一个正整数n(n<=10)(多组数据) Output 输出n的阶乘(每组数据一行) Sample Input 3 Sample Output 6

1131: 零起点学算法38——求阶乘和

1131: 零起点学算法38--求阶乘和 Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 2719  Accepted: 1736[Submit][Status][Web Board] Description 输入一个正整数n(n<=10),计算 S=1!+2!+3!+...+n! Input 输入一个正整数n(n<=10)(多组数据) Output 输出S(每组数据一行) Sample Inpu