欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > K短路(A*算法)

K短路(A*算法)

2025/2/24 15:21:43 来源:https://blog.csdn.net/m0_74453078/article/details/141073549  浏览:    关键词:K短路(A*算法)

K短路:

在图论中,K短路问题是指在一个图中找到从起点s到终点t的第K短的路径。其中,第1短路径即为最短路径。K短路算法在实际应用中有着广泛的用途,如在通信网络中找到替代的最短路径等。

基本概念
  • K短路:从起点s到终点t的第K短的路径。当K=1时,即为最短路径。
  • Dijkstra算法:一种用于求解单源最短路径的贪心算法,但只能找到一条最短路径。
  • A*算法:一种启发式搜索算法,通过估价函数f(n) = g(n) + h(n)来估计从起点到终点的路径长度,其中g(n)是从起点到当前节点的实际代价,h(n)是从当前节点到终点的最佳路径估计代价。
K短路算法的实现
1. 基于Dijkstra和A*的K短路算法

K短路算法的基本思想是在每次迭代中,找到从起点到终点的第K短路径。通常,我们结合Dijkstra算法和A*算法来实现这一目标。

步骤

  1. 预处理:使用Dijkstra算法从终点t反向计算图中每个节点到t的最短路径长度,存储在数组dis[]中。这个步骤是为了计算A*算法中的h(n)。
  2. 初始化:使用优先队列(最小堆)来存储待扩展的路径,队列中的元素包括当前路径的估价f(n)、实际代价g(n)和当前节点v。
  3. 迭代过程
    • 从队列中取出估价最小的节点now。
    • 如果now是终点t,并且这是第k次到达t,则返回当前路径的总代价。
    • 如果now到达t的次数超过k,则跳过此节点。
    • 否则,扩展now节点,生成所有可能的下一节点,并计算其估价f(next) = g(now) + w(now, next) + dis[next],其中w(now, next)是now到next的边的权重。
    • 将新的节点加入队列中。
  4. 结束条件:如果队列为空,表示没有找到第k条路径,返回-1或其他错误标识。

在这里插入图片描述

推荐相关视频学习链接:【B27 A*算法 第K短路】https://www.bilibili.com/video/BV19k4y1K7gV?vd_source=4c9eb38d8205116069b961c84f64c958

在这里插入图片描述

接下来看一下相关代码(此代码维护二元组)

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
typedef pair<int,int> pii;
const int N = 1e3 + 10, M = 1e5 + 10;int n, m, S, T, K;
int dist[N], st[N], cnt[N];
vector<pii> e[N], ne[N]; //e数组是用来存从终点T到其余各点的边,实际上是没有这些边的,只是将原来的单向边进行反向,就可以表示出从T到其余各点的边
struct node{int s, v, d;bool operator<(const node &x) const{return s > x.s;//如果你使用的是默认的比较函数std::less<T>(或者没有显式指定比较函数,因为std::less<T>是默认的),那么它会调用元素的operator<(如果已定义)。在这种情况下,operator<的bool返回值表示第一个元素是否“小于”第二个元素,而std::priority_queue会将这些“较小”的元素放在堆的底部(尽管它们仍然很容易被访问,但不是最先被移除的)。然而,由于std::priority_queue是一个最大堆,所以实际上被视为“最大”的元素(即那些operator<返回false的元素)会被放置在堆顶。}
};
void dijkstra() {memset(dist, 0x3f, sizeof dist);dist[T] = 0;//这里求的是从T为起点的,到其余各点的最短距离priority_queue<pii, vector<pii>, greater<pii>> q;q.push({0, T});while(q.size()) {int ver = q.top().second, dis = q.top().first;q.pop();if(st[ver]) continue;st[ver] = 1;for(pii t : e[ver]) {int u = t.first, w = t.second;if(!st[u] && dist[ver] + w < dist[u]) {dist[u] = dist[ver] + w;q.push({dist[u], u});}}}
}
int aStar() {priority_queue<node> q; q.push({dist[S], S, 0});while(q.size()) {int ver = q.top().v, dis = q.top().d;q.pop();cnt[ver]++;if(cnt[T] == K) return dis;for(pii t : ne[ver]) {int u = t.first, w = t.second;q.push({dist[u] + dis + w, u, dis + w});}} return 0;
}   
int main() {cin >> n >> m;for(int i = 1; i <= m; i++) {int a, b, c; cin >> a >> b >> c;ne[a].push_back({b, c});//这里建的是单向边e[b].push_back({a, c});//反向建边,和原来边一样,同样是单向边,只不过反向}cin >> S >> T >> K;if(S == T) K++; //这种情况对应有环,即可以自己到自己,第一次从自己出发,所以k++,去掉第一次dijkstra();//先预处理从T到其余各点的最短距离,即预测数组// for(int i = 1; i <= n; i++) {//     cout << "i: " << i << " dist[i]: " << dist[i] << '\n';// }cout << aStar();return 0;
}

在这里插入图片描述

在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词