A*算法+最短路实现K短路+模板题
<font color=black size=4>K短路问题还是很普遍的,了解一下K短路很有必要,顺便学会A*的简单应用更好。
A*算法,是一种启发式搜索算法,我们可以自己设定一个估价函数,这样我们的搜索过程就会优先选择有更好的估价函数的点进行搜索。
在最短路中,A*的估价函数定义如下:f(p)=g(p)+h(p),g(p)表示当前从起始点s到点p的距离,而h(p)就是从终点到p的最短路距离,(暂且是最短路,因为k短路必须由最短路出发向前找的,每次都是除了上一次的最短路),则f(p)就意味着从起点s到当前路径p之后再走到终点t的最短路,这样,我们的每次扩展都是有方向的扩展,从而降低求解速度和降低搜索的状态数,并且保证不优于最优解的同时尽量靠近最优解。
思路到了,做法也必须跟上。我们用最短路来估价,这就要求对h(p)函数进行一个预处理,所以我们可以求出终点到各个点的最短路,作为h(p)值,再从s开始遍历k次,每次都以上一次为最短路,直到我们第k次到达终点,此时的路径长度就是k短路。
</font>
<font color=black size=4>
详细部分看下面几个模板题的代码。
(1)POJ2449
题目链接:https://vjudge.net/problem/POJ-2449
题目大意:给出一个图,然后给出一个起点个一个终点,求这两点间的第K短路。
本题中是可以走重复的路的,所以如果一张图中有一个环的话,无论求第几短路都是存在的。
也就是,样例询问的第二短路,就是先从1到2,再从2到1,再从1到2,结果为5+4+5=14
代码:</font>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;/*POJ 2449 A*求k短路模板题
*/const int maxn=1005;
const int maxm=500005;
const int INF=0x3f3f3f3f;struct Edge
{int u;int v;int next;int w;
}edges[maxm],re_edges[maxm];//re_edges为反向边struct ANode
{int f,g,v;//分别对应f函数,g函数和v编号bool operator <(const ANode &rhs)const{if(rhs.f==f)return rhs.g<g;return f>rhs.f;//f小的优先被考虑}ANode(int _f,int _g,int _v):f(_f),g(_g),v(_v){}
};
int head[maxn],re_head[maxn],tot;
void init()
{memset(head,-1,sizeof(head));memset(re_head,-1,sizeof(re_head));tot=0;
}
int dis[maxn];
int vis[maxn];
int n,m,S,T,k;void add_edges(int u,int v,int cost)
{edges[tot].u=u;edges[tot].v=v;edges[tot].w=cost;edges[tot].next=head[u];head[u]=tot;//反向边,因为要计算点p到最终点的最短路,就直接计算最终点到p的最短路re_edges[tot].u=v;re_edges[tot].v=u;re_edges[tot].w=cost;re_edges[tot].next=re_head[u];re_head[u]=tot++;
}//处理一个距离数组,表示从终点开始到各个点的最短路int cnt[maxn];//每个点的入队次数
bool SPFA(int s)
{for(int i=1;i<=n;i++)dis[i]=INF;memset(vis,0,sizeof(vis));queue<int>Q;while(!Q.empty())Q.pop();vis[s]=1;dis[s]=0;Q.push(s);memset(cnt,0,sizeof(cnt));cnt[s]=1;while(!Q.empty()){int u=Q.front();Q.pop();vis[u]=0;for(int i=re_head[u];i!=-1;i=re_edges[i].next){int v=edges[i].v;int w=edges[i].w;if(dis[v]>dis[u]+w){dis[v]=dis[u]+w;if(!vis[v]){Q.push(v);vis[v]=1;if(++cnt[v]>n)return false;}}}}return true;
}int A_star(int s,int t)
{int cnt=0;//计数,计k短路priority_queue<ANode>Q;if(s==t)k++;if(dis[s]==INF)return -1;Q.push(ANode(dis[s],0,s));while(!Q.empty()){ANode temp=Q.top();Q.pop();int u=temp.v;if(u==t){cnt++;if(cnt==k)return temp.g;}for(int i=head[u];i!=-1;i=edges[i].next){//移动,更新节点的估计函数int v=edges[i].v;int g=temp.g+edges[i].w;int f=g+dis[v];Q.push(ANode(f,g,v));}}return -1;
}int main()
{while(scanf("%d%d",&n,&m)!=EOF){init();for(int i=0;i<m;i++){int x,y,w;scanf("%d%d%d",&x,&y,&w);add_edges(x,y,w);}scanf("%d%d%d",&S,&T,&k);if(SPFA(S)){printf("%d\n",A_star(S,T));}else{printf("-1\n");}}return 0;
}
<font color=black size=4>(2)2018 ACM-ICPC沈阳网络赛——D——Made in Heaven
题目链接:https://nanti.jisuanke.com/t/31445
也是一个k短路裸题,模板改一改就能过啦。
代码:</font>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;/*A*求k短路模板题
*/const int maxn=1005;
const int maxm=10000+50;
const int INF=0x3f3f3f3f;struct Edge
{int u;int v;int next;int w;
}edges[maxm],re_edges[maxm];//re_edges为反向边struct ANode
{int f,g,v;//分别对应f函数,g函数和v编号bool operator <(const ANode &rhs)const{if(rhs.f==f)return rhs.g<g;return f>rhs.f;//f小的优先被考虑}ANode(int _f,int _g,int _v):f(_f),g(_g),v(_v){}
};
int head[maxn],re_head[maxn],tot;
void init()
{memset(head,-1,sizeof(head));memset(re_head,-1,sizeof(re_head));tot=0;
}
int dis[maxn];
int vis[maxn];
int n,m,S,T,k;void add_edges(int u,int v,int cost)
{edges[tot].u=u;edges[tot].v=v;edges[tot].w=cost;edges[tot].next=head[u];head[u]=tot;//反向边,因为要计算点p到最终点的最短路,就直接计算最终点到p的最短路re_edges[tot].u=v;re_edges[tot].v=u;re_edges[tot].w=cost;re_edges[tot].next=re_head[u];re_head[u]=tot++;
}//处理一个距离数组,表示从终点开始到各个点的最短路int cnt[maxn];//每个点的入队次数
bool SPFA(int s)
{for(int i=1;i<=n;i++)dis[i]=INF;memset(vis,0,sizeof(vis));queue<int>Q;while(!Q.empty())Q.pop();vis[s]=1;dis[s]=0;Q.push(s);memset(cnt,0,sizeof(cnt));cnt[s]=1;while(!Q.empty()){int u=Q.front();Q.pop();vis[u]=0;for(int i=re_head[u];i!=-1;i=re_edges[i].next){int v=edges[i].v;int w=edges[i].w;if(dis[v]>dis[u]+w){dis[v]=dis[u]+w;if(!vis[v]){Q.push(v);vis[v]=1;if(++cnt[v]>n)return false;}}}}return true;
}int A_star(int s,int t)
{int cnt=0;//计数,计k短路priority_queue<ANode>Q;if(s==t)k++;if(dis[s]==INF)return -1;Q.push(ANode(dis[s],0,s));while(!Q.empty()){ANode temp=Q.top();Q.pop();int u=temp.v;if(u==t){cnt++;if(cnt==k)return temp.g;}for(int i=head[u];i!=-1;i=edges[i].next){//移动,更新节点的估计函数int v=edges[i].v;int g=temp.g+edges[i].w;int f=g+dis[v];Q.push(ANode(f,g,v));}}return -1;
}int main()
{int time;while(scanf("%d%d",&n,&m)!=EOF){scanf("%d%d%d%d",&S,&T,&k,&time);for(int i=0;i<m;i++){int x,y,w;scanf("%d%d%d",&x,&y,&w);add_edges(x,y,w);}if(SPFA(T)){int ans=A_star(S,T);if(ans==-1||ans>time)printf("Whitesnake!\n");elseprintf("yareyaredawa\n");}elseprintf("yareyaredawa\n");}return 0;
}
A*算法+最短路实现K短路+模板题相关推荐
- 【图论算法】 最短路,次短路,k短路总结
在图论里,最短路,次短路,k短路的问题很常见. 这里总结一下. 存图技巧 数据小,稠密图的一般用邻接矩阵 稀疏图,数据大一般用邻接表(vector,链式前向星都可) 邻接矩阵 const int ma ...
- 匈牙利算法——最大匹配问题详解(附模板题)
基本概念转自 https://blog.csdn.net/dengheCSDN/article/details/77619308 匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名. ...
- 1163. 第K短路
Description Bessie 来到一个小农场,有时她想回老家看看她的一位好友.她不想太早地回到老家,因为她喜欢途中的美丽风景.她决定选择K短路径,而不是最短路径. 农村有 R (1≤R≤100 ...
- ACM-ICPC 2018 沈阳赛区网络预赛 D. Made In Heaven (K短路算法模板)
题意 : 求第k短路的权值是否超过T(权值) 解法: 网上随便找的一个求K短路的算法模板套弄一下即可 (模板要好,不然邻接表存图会TLE , 网上换了两个模板才AC的) AC代码: #include& ...
- A*算法的认识与求第K短路模板
现在来了解A*算法是什么 现在来解决A*求K短路问题 在一个有权图中,从起点到终点最短的路径成为最短路,第2短的路成为次短路,第3短的路成为第3短路,依此类推,第k短的路成为第k短路.那么,第k短路怎 ...
- 第k短路 算法详解(图解)与模板(A* 算法)
本博文来自bestsort (转载请保留此信息) A*是一种启发式搜索,根据目标地点和当前点的距离和估计要走的步数来决策下一步走哪个方向.而这两个参数,一般用g(x)g(x)g(x)和h(x)h(x) ...
- 第k短路 (A*算法)
A*算法: A*,启发式搜索,是一种较为有效的搜索方法. 我们在搜索的时候,很多时候在当前状态,已经不是最优解了,但是我们却继续求解:这个就是暴力搜索浪费时间的原因. 我们在有些时候,往往可以根据一些 ...
- poj2449 K短路模板题
昨晚看WC论文发现自己连K短路的经典A*算法还不会,补了一波,模板题输出-1后没return继续跑wa了一早上...... 算法流程: ①在反向图中求出t到每个点的最短路 ②从原点bfs,估价f=d+ ...
- poj2449(k短路算法)
K 短路问题(A* 启发式广搜) 1.k 短路问题就是最短路问题的延申,要找出第 k 短的路径.用广搜进行路径查找,第一次找到的 就是最短路,第二次找到的是第 2 短 路⋯以此类推.所以我们只需要一直 ...
最新文章
- JSP作用域与特殊对象
- 初二计算机辅导记录,信息技术指导老师的讲课笔记十篇(2)
- linux下重启weblogic
- .exe已停止工作_Windows 10累积更新KB4565503和KB4565483已发布
- 如何做到行业顶尖位置?
- 17.go 面向对象 interface
- 【脑电信号】基于matlab SVM分期睡眠监测【含Matlab源码 611期】
- 云客Drupal源码分析之节点表单NodeForm
- 帝国cms 自定义页面 php,帝国CMS增加自定义页面模板修改教程
- 火车头采集器AI伪原创v.2.3
- 3D扁平化高绩效五项管理PPT模板
- 武汉大学计算机系英语挂科,挂科率最高的前100所大学 武大挂的最多的居然是...
- “人工智能发展现状”
- 环信开发的坑(环信客户互动云)
- 你知道外卖cps是什么吗?(附裂变分销小程序源码搭建教程)
- 基于ssm框架的校园二手交易平台
- 小学妹听了都说棒的:国王试毒酒问题
- UML-----包图
- sim7000c驱动_SIM7000C硬件设计手册_V1.00-SIMCom.PDF
- 华为ws851虚拟服务器,华为WS851路由器的安装教程