A*算法
A*算法在求一个点到目标点的最短距离时,可以加快速度,如果使用dijstla是nlogn的时复,但是A*更快,当节点足够多,边足够大时,可能不能求起点到所有点的最短距离,空间不够或者时复顶不住,这个时候A*或许能做,A使用了一个启发式函数f(),其含义是节点到终点的估计距离,这个距离可以是曼哈顿距离,可以是实际到终点的最短距离等等,只要满足*估计距离小于等于实际距离即可,只要满足了这个,那么用f(u)+dis(u)当作优先队列的排序规则,每次取出最小值,这个点的最短距离就确定了,证明我找不到,
画个图可以想一下是有道理的
ACWing.178.第K短路
我看到这道题,不会A之前,我只能想到Knlogn的时复,跑K次dijstla…太菜了,其实更好的是使用BFS,给每一个状态加上一个距离,使用优先队列,每次取出距离最小的点,其实就是dijstla,只不过少了dis数组,这样子做如果不加优化空间和时间都顶不住,所以开一个cnt[]数组记录每一个点被更新了几次,如果一个点已经被更新K次了,之后这个点就没必要再入队了,加上这个优化后,时复和空间复杂度最坏就是Knlogn,但是这道题还是过不去,所以使用A\优化,加上f()函数,表示从终点到节点的最短距离作为近似值,估计值=节点距离起点的距离+距离终点的距离近似值,以估计值作为排序标准,每次取出最小,当终点被第K次取出时返回答案。
需要说明的时这个题目是可能存在重边的,所以必须等一个点把能到的状态都走完,才能判断返回条件。
1 | for(int i=h[u.to];~i;i=e[i].next){ |
这个写法是错误的,假如1->2有很多边权,存边的时候是按照来的顺序存的,所以可能是乱的,除非用vector存边而且边权排序,否则答案不对,还有这道题每条最短路中至少要包含一条边,所以如果终点和起点相同,找的是第K+1条边。
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Doraemon's Blog!
评论