POJ - 2449 Remmarguts' Date(第k短路:spfa+A*)
题目链接:点击查看
题目大意:给出一个有向图,求第k短路
题目分析:偷学了一波A*,本来以为是多难的算法,其实就是bfs+优先队列的升级版,之前看的那些博客写的都太深奥了,以至于看了一半啥都没看懂然后就被吓跑了,这里放一波zx学长PPT上的描述,我感觉简洁精炼,几句话就把这个算法的核心描述清楚了:
- A * 算法的实现,A * =优先队列BFS+估价函数。
- 回顾优先队列bfs:优先队列BFS算法维护了一个优先队列,不断从堆中取出当前代价最小的状态进行扩展。每个状态第一次从堆中取出时,就得到了从初态到该状态的最小代价。
- 局限:如果给定一个目标状态,需要求出从初态到目标状态的最小代价,那么优先队列BFS这个优先策略是不完善的。一个状态当前代价小,只能说明从起始状态到该状态代价小,而在未来的搜索中从该状态到目标状态的花费可能会很大。导致有一部分很晚才能得到扩展。
- 为了提高搜索效率,我们很自然的想到,可以对未来可能产生的代价进行预估。
- 详细的讲:我们设计一个估价函数,以任意状态为输入,计算出从该状态到目标状态所需代价的估计值。在搜索中,仍然维护一个堆,不断从堆中取出 当前代价+未来估价 最小的状态进行扩展
- 为了保证第一次从堆中取出目标状态时得到的就是最优解,我们设计的估价函数需要满足一个基本准则:估价函数的估值不能大于未来实际代价,估价比实际代价更优。
- 这种带有估价函数的优先队列BFS就称为A * 算法。只要保证对于任意状态state,都有f(state)≤g(state),A * 算法就一定能在目标状态第一次从堆中被取出时得到最优解,并且在搜索过程中每个状态只需要被扩展一次(之后再被取出就可以直接忽略)。估价f(state)越准确,越接近g(state),A * 算法的效率就越高。如果估价始终为0,就等价于普通优先队列BFS。
- A * 算法提高搜索效率的关键,就在于能否设计出一个优秀的估价函数。估价函数在满足上述设计准则的前提下,含应该尽可能反映未来实际代价的变化趋势和相对大小关系,这样搜索才会较快的逼近最优解
- 估价函数的设计准则:
- 估值f(state)≤未来实际代价g(state)
那么再回到这个题目上面,我们只需要设计出估价函数即可,这个题目的权值是距离,当我们到达一个点后,利用bfs的状态转移可以很容易的知道从起点到当前点的距离,那怎么知道当前点到终点的距离呢?我们可以一开始从终点跑一遍迪杰斯特拉或者spfa,这样就能轻松表达出估价函数了,有了估价函数后,我们在优先队列+bfs的基础上,更改排序函数的机制为估价函数,然后给我们的bfs函数改个名字,就变成A*算法了
有一个坑点需要注意一下,当终点和起点重合的时候,我们需要让k++,以避免出现让起点直接到达终点的现象发生
代码,模板题:
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e3+100;int d[N];bool vis[N];struct Node
{int to,w;Node(int TO,int W){to=TO;w=W;}Node(){}bool operator<(const Node& a)const{return w+d[to]>a.w+d[a.to];}
};vector<Node>node1[N],node2[N];//1:正向边 2:反向边 void spfa(int x)
{memset(vis,false,sizeof(vis));memset(d,inf,sizeof(d));queue<int>q;q.push(x);d[x]=0;vis[x]=true;while(!q.empty()){int from=q.front();q.pop();vis[from]=false;for(int i=0;i<node2[from].size();i++){int to=node2[from][i].to;int w=node2[from][i].w;if(d[to]>d[from]+w){d[to]=d[from]+w;if(!vis[to]){vis[to]=true;q.push(to);}}}}
}int A_star(int start,int end,int k)
{priority_queue<Node>q;q.push(Node(start,0));while(!q.empty()){Node cur=q.top();q.pop();if(cur.to==end){k--;if(!k)return cur.w;}for(int i=0;i<node1[cur.to].size();i++){int to=node1[cur.to][i].to;int w=node1[cur.to][i].w;q.push(Node(to,cur.w+w));}}return -1;
}int main()
{
// freopen("input.txt","r",stdin);int n,m;while(scanf("%d%d",&n,&m)!=EOF){for(int i=1;i<=n;i++){node1[i].clear();node2[i].clear();}while(m--){int u,v,w;scanf("%d%d%d",&u,&v,&w);node1[u].push_back(Node(v,w));node2[v].push_back(Node(u,w));}int s,e,k;scanf("%d%d%d",&s,&e,&k);spfa(e);if(d[s]==inf){printf("-1\n");continue;}if(s==e)//特判一下,坑 k++;printf("%d\n",A_star(s,e,k));}return 0;
}
POJ - 2449 Remmarguts' Date(第k短路:spfa+A*)相关推荐
- POJ 2449 Remmarguts' Date [第k短路]
Remmarguts' Date Time Limit: 4000MS Memory Limit: 65536KB 64bit IO Format: %lld & %llu Descripti ...
- POJ 2449 Remmarguts' Date(第K短路 + A* + 最短路)题解
题意:找出第k短路,输出长度,没有输出-1 思路:这题可以用A*做.A*的原理是这样,我们用一个函数:f = g + h 来表示当前点的预期步数,f代表当前点的预期步数,g代表从起点走到当前的步数,h ...
- POJ 2449 Remmarguts' Date(k短路模板)
link:https://vjudge.net/problem/POJ-2449 前面输入与大多最短路题相同 最后一行输入s,t,k 求从s到t的第K短路 wiki link: https://en. ...
- poj2449 Remmarguts' Date(第k短路问题)(A*+spfa/dijkstra)
思路来源 https://blog.csdn.net/berrykanry/article/details/78345894(通俗易懂解释好评) https://www.cnblogs.com/yyf ...
- poj 2449 Remmarguts' Date 启发式搜索 A*算法
做这个题算是学了学spfa算法,一开始感觉spfa和dij好像:dij找最小点松弛,spfa就是一个一个的松弛,松到不能松. 求S到T的第K短路 思路:这个算法的思路是从源点S优雅的暴力跑bfs,用优 ...
- POJ 2449 Remmarguts' Date
POJ_2449 一开始我的思路就是把图上每个点搞一个容量不小于K的最大堆和最小堆,最小堆用于取当前该节点的第某短路值,最大堆用来保存前K小的最短路. 最后为了每次能查询全局最小值,再把N个点放到一个 ...
- 【POJ】3255 Roadblocks(次短路+spfa)
http://poj.org/problem?id=3255 同匈牙利游戏. 但是我发现了一个致命bug. 就是在匈牙利那篇,应该dis2单独if,而不是else if,因为dis2和dis1相对独立 ...
- A*算法的认识与求第K短路模板
现在来了解A*算法是什么 现在来解决A*求K短路问题 在一个有权图中,从起点到终点最短的路径成为最短路,第2短的路成为次短路,第3短的路成为第3短路,依此类推,第k短的路成为第k短路.那么,第k短路怎 ...
- Poj2449 Remmarguts' Date 【A*搜索】K短路
http://poj.org/problem?id=2449 A*搜索求K短路. #include <cstdio> #include <cstring> #include & ...
最新文章
- LeetCode中等题之特殊等价字符串组
- 机器学习基础--基本术语
- 这样的烂代码,我实习的时候都写不出来!
- jemter编写Mysql脚本___传参
- linux deploy 版本,Linux Deploy
- DataGridView 单元格验证
- python实现RSA算法,对数据进行加密认证
- 【C语言】 删除一个字符串中重复的字符
- ARM全新Armv9架构:10年最大更新、增强AI和security能力
- Microsoft Visual Studio使用NodeJS
- 电子换向电动机行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
- 解决办法:nvidia-docker2 : 依赖: docker-ce (= 5:18.09.0~3-0~ubuntu-xenial)
- 淘宝手淘搜索怎么做?大神导航,一个神奇的网站,从此开启大神之路!
- [SUCTF 2018]GetShell
- uni-app设置屏幕亮度
- 2023昆明理工大学计算机考研信息汇总
- Revit模型轻量化方法
- python的镜像安装和设置
- 聚簇索引与非聚簇索引
- 心流_追求生命的意义