POJ 2449 Remmarguts' Date A*+spfa求第k最短路

来源:互联网 发布:监控远程软件 编辑:程序博客网 时间:2024/06/06 08:45

题目链接

题意:

给你个图 让你求s到t的第k短路\

思路:

首先讲讲A*算法吧。众所周知,A*算法就是启发式搜索,基本形式就是这样:f(x)=g(x)+h(x);其中f(x)代表在x点所需要的总代

价,而g(x)代表:从源点到x点已经耗费的实际代价,h(x)代表从x到终点需要的估计代价,这个函数是一个估计值.而从x到终点真正需

要的代价为h*(x),在整个启发式搜索中我们必须保证h(x)<=h*(x);不然的话会由于对当前的估价值过高,则会引起答案的错误。构建A*的

关键在于准确的规划一个h(x)函数,使得接近h*(x),这样的搜索会使得答案又快又准。可以想象h(x)过小会使得解空间过大,这样搜索出来

的结果会很准确但是速度太慢,而对h(x)的过高估计,即估计代价太大会使得结果不准确。

这样我们可以理解了BFS的搜索过程,BFS的搜索过程中没有考虑到h(x)的估计代价,也就是说h(x)=0,只考虑g(x)的实际代价。这样根

据实际代价来进行搜索,虽然可以说是很恶心的A*,同样地我们可以知道,BFS的解空间确实很大。

第一次写A*,目前只会应用在K短路上。不过也有点感觉了,关键在于h(x)的设计!


具体实现的话就是用优先队列每次取出估价函数最小的去扩展,这里的f(n)实际上就是代表了从s走到n后再从n走到t的距离.所以我们选取最小的 才能更快的去降低求解的范围提高求解速率,使其有方向的扩展.关于这里的h(n)我们用n到t的最短距离来表示,这个估计代价是准确的,我们反向建图跑一遍spfa求t到其余各个点的最短路.



我们开一个变量标记t出现了几次 出现了k次的时候 就是第k短路了

#include<stdio.h>#include<iostream>#include<queue>#include<vector>#include<string.h>#define PT printf#define SC scanf#define mod 99991#define inf 0x3f3f3f3fusing namespace std;const int maxn=1e3+10;const int mm=1e5+10;typedef long long ll;int n,m; int s,t,k;int dis[maxn];int book[maxn];struct node{int to;int cost;};struct A{int f;int g;int v;friend bool operator<(A a,A b ){if(a.f==b.f)return a.g>b.g;return a.f>b.f;}};vector<node>edge[maxn],ff[maxn];void spfa(){memset(dis,inf,sizeof(dis));memset(book,0,sizeof(book));dis[t]=0;book[t]=1;queue<int>qt;qt.push(t);while(!qt.empty()){int w=qt.front();qt.pop();for(int i=0;i<ff[w].size();i++){int tt=ff[w][i].to;if(dis[tt]>dis[w]+ff[w][i].cost){dis[tt]=dis[w]+ff[w][i].cost;if(!book[tt]){book[tt]=1;qt.push(tt);}}}book[w]=0;}return ;}int Astar(){priority_queue<A>Q;int time=0;if(dis[s]==inf)return -1;A x,y;x.v=s,x.g=0,x.f=dis[s]+x.g;Q.push(x);while(!Q.empty()){y=Q.top();Q.pop();if(y.v==t){time++;if(time==k)  return y.g;}for(int i=0;i<edge[y.v].size();i++){x.v=edge[y.v][i].to;x.g= y.g+edge[y.v][i].cost;x.f=x.g+dis[x.v];Q.push(x);}}return -1;}int main(){int a,b;node c;scanf("%d %d",&n,&m);for(int i=1;i<=m;i++){scanf("%d %d %d",&a,&c.to,&c.cost);edge[a].push_back(c);b=c.to;c.to=a;ff[b].push_back(c);}scanf("%d %d %d",&s,&t,&k);if(s==t)k++;spfa(); printf("%d\n",Astar()); return 0;}

0 0
原创粉丝点击