现在来了解A*算法是什么

现在来解决A*求K短路问题

 在一个有权图中,从起点到终点最短的路径成为最短路,第2短的路成为次短路,第3短的路成为第3短路,依此类推,第k短的路成为第k短路。那么,第k短路怎么求呢?

  对于第k短路,可以想到的一个比较朴素的算法就是广度优先搜索,使用优先队列从源点s进行广搜,当第k次搜索到终点t时,所的长度即所求但是这种方法在运行过程中会产生特别多的状态,当图比较简单、k比较小时,可以一试,但是当k较大或者图中点数较多时,会面临爆栈的危险。目前使用比较多的算法是单源最短路配合A*。A*是搜索中比较高级的方式,A*算法结合了启发式方法(这种方法通过充分利用图给出的信息来动态的作出决定而使搜索次数大大降低)和形式化方法(这种方法不利用图给出的信息,而仅通过数学的形式分析,如Dijkstra算法)。它通过一个估价函数f(h)来估计图中的当前点p到终点的距离,并由此决定它的搜索方向,当这条路径失败时,它会尝试其他路径。对于A*,估价函数=当前值+当前位置到终点的距离,即f(p)=g(p)+h(p),每次扩展估价函数值最小的一个。对于第k短路算法来说,g(p)为从源点s到当前点p所走的路径长度,h(p)为从当前点p到终点t的最短路,因此f(p)的意义就是从s按照当前路径经过p点后到达t的总距离。也就是每次扩展都是有方向的,这样无论对提高出解的速度还是降低扩展的状态数目都是有好处的。为了加快计算,h(p)需要在搜索之前进行预处理,只要将原图的所有边反向,再从终点t做一次单源最短路即可得到h(p)。单源最短路求法有Dijkstra,Bellman-Ford,SPFA等。

  具体步奏:

  这里我们使用链式前向星来存储如图,由于需要预处理所有点到终点的最短路,就需要将图G中所有边反向得到图G',再从终点t做一次单源最短路,所以实际上就是两张图。

  (1)将有向图的所有边反向(无向图可以省略此步),以原图终点t为源点做一次单源最短路,结果记入数组dis[i]中,dis[i]即为原图中点i到点t的最短距离。这里的dis[i]即上述的h(p);

  (2)新建一个优先队列,将源点s加入到队列中;

  (3)从优先队列中弹出f(p)最小的点p(这里如果存在f(p)相等的点,则弹出g(p)最小的点),如果点p就是终点t,则计算t出队列的次数,如果当前为t的第k次出队,则当前路径长度就是s到t的第k短路,算法结束;否则遍历与p相连的所有的边,将扩展出的到p的邻接点信息加入到优先队列。

  值得注意的是,当s==t时需要计算(k+1)短路,因为s到t这条距离为0的路不能算在这k短路中,这时只需将k自增1后再求第k短路即可。

现在来实战下:

POJ 2449 Remmarguts' Date ( 第 k 短路 && A*算法 )

题意 : 给出一个有向图、求起点 s 到终点 t 的第 k 短路、不存在则输出 -1

#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
const int INF  = 0x3f3f3f3f;
const int maxn = 1024;
const int maxm = 100008;
struct EDGE{ int v, nxt, w; };
struct NODE{int pos, Cost, F;bool operator < (const NODE & rhs) const {//重载的时候注意符号if(this->F == rhs.F) return this->Cost > rhs.Cost;return this->F > rhs.F;};
};EDGE Edge[maxm];
EDGE REdge[maxm];
int Head[maxn], RHead[maxn];
int cnt, Rcnt;
int N;
void init()
{memset(Head, -1, sizeof(Head));memset(RHead, -1, sizeof(RHead));cnt = Rcnt = 0;
}void AddEdge(int from, int to, int weight)
{Edge[cnt].w = weight;Edge[cnt].v = to;Edge[cnt].nxt = Head[from];Head[from] = cnt++;
}void AddREdge(int from, int to, int weight)
{REdge[Rcnt].w = weight;REdge[Rcnt].v = to;REdge[Rcnt].nxt = RHead[from];RHead[from] = Rcnt++;
}int vis[maxn];
int H[maxn];
void SPFA(int st)
{queue<int> que;memset(H, INF, sizeof(H));memset(vis, 0, sizeof(vis));H[st] = 0;que.push(st);while(!que.empty()){int cur = que.front(); que.pop();vis[cur] = 0;for(int i=RHead[cur]; i!=-1; i=REdge[i].nxt) {int v = REdge[i].v;if(H[v] > H[cur] + REdge[i].w) {H[v] = H[cur] + REdge[i].w;if(!vis[v]) {vis[v] = 1;que.push(v);}}}}
}int A_Star(int s, int t, int k)
{if(s == t) k++;if(H[s]==INF) return -1;priority_queue<NODE> que;NODE cur, into;cur.pos = s;cur.Cost = 0;cur.F = H[s];que.push(cur);int CNT = 0;while(!que.empty()){cur = que.top();que.pop();if(cur.pos == t) CNT++;if(CNT == k) return cur.Cost;for(int i=Head[cur.pos]; i!=-1; i=Edge[i].nxt){into.Cost = cur.Cost+Edge[i].w;into.F = cur.Cost+Edge[i].w+H[Edge[i].v];into.pos = Edge[i].v;que.push(into);}}return -1;
}int main(void)
{int M, K, S, des;while(~scanf("%d %d", &N, &M)){init();int from, to, weight;while(M--){scanf("%d %d %d",&from, &to, &weight);AddEdge(from, to, weight);AddREdge(to, from, weight);//建反向边
        }scanf("%d %d %d", &S, &des, &K);SPFA(des);//求其他点到终点的最短路,作为H值printf("%d\n", A_Star(S,des,K));}return 0;
}

View Code

转载于:https://www.cnblogs.com/shuaihui520/p/9623597.html

A*算法的认识与求第K短路模板相关推荐

  1. A*算法+最短路实现K短路+模板题

    <font color=black size=4>K短路问题还是很普遍的,了解一下K短路很有必要,顺便学会A*的简单应用更好. A*算法,是一种启发式搜索算法,我们可以自己设定一个估价函数 ...

  2. 综合算法02—指定点之间的K短路

    %注意:程序中调用了Dijkstras算法,若需要运行,请自行将其放在同目录下. function [W_Section,Line_Section_01Mat,Mxf]=KSP(Road_Net,Li ...

  3. 树状数组与离散化与求第K大模板

    树状数组模板: //Cnt为数组的界 //cnt[i]为编号或者数值上小于id的数量 void Update(LL Id) {while(Id<=Cnt){cnt[Id]++;Id+=lowbi ...

  4. POJ 2449 Remmarguts' Date(k短路模板)

    link:https://vjudge.net/problem/POJ-2449 前面输入与大多最短路题相同 最后一行输入s,t,k 求从s到t的第K短路 wiki link: https://en. ...

  5. poj2449 K短路模板题

    昨晚看WC论文发现自己连K短路的经典A*算法还不会,补了一波,模板题输出-1后没return继续跑wa了一早上...... 算法流程: ①在反向图中求出t到每个点的最短路 ②从原点bfs,估价f=d+ ...

  6. 第K短路模板【POJ2449 / 洛谷2483 / BZOJ1975 / HDU6181】

    1.到底如何求k短路的? 我们考虑,要求k短路,要先求出最短路/次短路/第三短路--/第(k-1)短路,然后访问到第k短路. 接下来的方法就是如此操作的. 2.f(x)的意义? 我们得到的f(x)更小 ...

  7. 浅谈K短路算法(KSP)之一(A*算法求解)

    对于具有n个顶点和m条边且边的权值非负的简单图(无重边和环),K短路,是指的起点s到终点t的最短路径中第k个最小的.K短路分为有限制的K短路和无限制的K短路,有限制的K短路是指求得的路径中不含有回路( ...

  8. ACM-ICPC 2018 沈阳赛区网络预赛 D. Made In Heaven (K短路算法模板)

    题意 : 求第k短路的权值是否超过T(权值) 解法: 网上随便找的一个求K短路的算法模板套弄一下即可 (模板要好,不然邻接表存图会TLE , 网上换了两个模板才AC的) AC代码: #include& ...

  9. 综合算法05—考虑换乘的K短路算法

    一.问题描述 在路网中,已知站点.线路和线路-站点数据,有条件: 1.考虑到换乘时要花费一定的时间,因此对换乘路径费用要加上换乘时间. 2.当路网复杂时,为了避免多余计算,定义有效路径,使得路径在有效 ...

最新文章

  1. 《强化学习周刊》第12期:强化学习应用之组合优化
  2. MySQL性能优化速记
  3. JQuery解析JSON数据
  4. python新手入门-python新手入门方法
  5. c++ 外部组件发生异常_谁再悄咪咪的吃掉异常,我上去就是一 JIO
  6. Braess’paradox 布雷斯悖论
  7. zabbix常用key和自定义key的讲解
  8. word 职称计算机考试大纲,全国职称计算机考试Word2003大纲.doc
  9. stream对多个字段分组_java8 stream 如何按多字段分组,并对一个字段求和
  10. 内核并发控制---顺序锁 (来自网易)
  11. 轻量级网络模型之MobileNet系列
  12. ]flume高并发优化——(1)load_balance
  13. 计算机类教材的选题策划,电子计算机类科技期刊的选题策划.doc
  14. COMSOL 固体力学 第一主应力、第二主应力、第三主应力、径向应力、环向应力、切向应力 截面一维曲线
  15. Android上图片文字识别
  16. python二元一次方程组用鸡兔同笼的思路来写编程_应用二元一次方程组——鸡兔同笼教学设计...
  17. HTML表格表格标签的属性
  18. UE4-角色摄像机镜头的设置
  19. 解决阿里云FTP 227 Entering Passive Mode
  20. 全面理解ERP和APS:用饭局的例子说明,MRP 还是APS

热门文章

  1. centos 的关机命令
  2. 数据中心使用dtu远程连接oracel 9i数据库问题
  3. Android全局修改字体大小,Android 仿微信全局字体大小调整
  4. JSP中实现网页访问统计的方法
  5. Android学习:自定义ViewGroup方法总结
  6. MYSQL_使用外键约束(constraint)或触发器(trigger)来进行级联更新、删除
  7. 【树型DP】BZOJ1564 二叉查找树(noi2009)
  8. 浅谈redis数据库的键值设计
  9. 实例讲解UML建模分析与设计
  10. 史上最全,最完美的 JAVA 技术体系思维导图总结,没有之一!