poj2449--A*算法求解k短路

来源:互联网 发布:北京云计算公司 编辑:程序博客网 时间:2024/05/02 22:49

今天想到了以前早就遗留下来的一个算法–A*算法,基本上,我对于A*只有过简单的了解,却从来没有具体的写过 A*,于是就有了今天的A*学习。

A*算法相比与其他的搜索来说,它多了一个估价函数而已。而估价函数在不同的题目中形式又不同,这正是A*难的地方啊~

对于此题:给出n个点,m条边,可能又重边,给定起点,终点,求k短路。

k短路是A*的一个最简单的应用。
我们可以设计这样的估价函数:
f(u)=g(u)+h(u).f来代表从s到t的总代价,g为s到u的总代价,h是剩下路径的总代价。于是我们可以从t跑一遍spfa,来求解出t到每个点的距离,然后将其加入优先队列中,我们可以知道,k短路即优先队列中第k个到达t的路径。
注意:估价函数的估计代价一定比实际代价少,这样才能是A*满足条件。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#include<queue>#define For(aa,bb,cc) for(int aa=bb;aa<=cc;++aa)#define Set(aa,bb) memset(aa,bb,sizeof(aa))using namespace std;const int maxn=100010,maxm=1010,inf=0x3f3f3f3f;int be[maxn],ne[maxn],to[maxn],w[maxn],e;int revbe[maxn],revne[maxn],revto[maxn],revw[maxn],reve;int dis[maxm];bool vis[maxn];int n,m,s,t,k;struct Astar{    int f,g,p;//f表示路程和,g表好已经走过的路程,h表示对应的点    bool operator <(const Astar a)const{        return f==a.f?g>a.g:f>a.f;    }};void add(int x,int y,int z){    ne[++e]=be[x],be[x]=e,to[e]=y,w[e]=z;    revne[e]=revbe[y],revbe[y]=e,revto[e]=x,revw[e]=z;}void spfa(int node){    For(i,1,n) dis[i]=inf,vis[i]=0;    dis[node]=0;    int q[maxn],f=0,l=0;    q[++l]=node;vis[node]=1;    while(f<l){        int ls=q[++f];vis[ls]=0;        for(int i=revbe[ls];i;i=revne[i]){            int u=revto[i];            if(dis[u]>dis[ls]+revw[i]){                dis[u]=dis[ls]+revw[i];                if(!vis[u]){                    vis[u]=1;                    q[++l]=u;                }            }        }    }}int A_star(int l,int r){    if(dis[l]==inf) return -1;    if(l==r) ++k;    priority_queue<Astar>q;    Astar now;    now.g=0,now.p=l,now.f=dis[l];    q.push(now);    int sum=0;    while(!q.empty()){        Astar ls=q.top();q.pop();        if(ls.p==r){            ++sum;            if(sum==k) return ls.g;        }        for(int i=be[ls.p];i;i=ne[i]){            now.p=to[i];            now.g=ls.g+w[i];            now.f=now.g+dis[to[i]];            q.push(now);        }    }    return -1;}void work(){    scanf("%d%d",&n,&m);    For(i,1,m){        int x,y,z;        scanf("%d%d%d",&x,&y,&z);        add(x,y,z);    }    scanf("%d%d%d",&s,&t,&k);    spfa(t);    printf("%d\n",A_star(s,t));}int main(){#ifndef ONLINE_JUDGE     freopen("in.txt","r",stdin);    freopen("out.txt","w",stdout);#endif    work();    return 0;}
0 1
原创粉丝点击