K短路及其模板(A*+Dijkstra)

来源:互联网 发布:淘宝消保金怎么退 编辑:程序博客网 时间:2024/06/05 20:46

阅读之前,先声明,您不需要对于A*算法多么深入的理解,事实上这对您对于K短路的理解帮助并不很大。当然,若果您对于A*已经有了自己独到见解,也是很好的。

A*

用非专业的语言来说,A*就是一个将最好的选择,送上你面前的算法。打个比方,您在一个叉路口,面前有几条路。A*做的,便是告诉您哪一条路是您最好的选择。

有一个这样的估价函数

        F = G + H

您可以简单的理解为F为您选择道路的标准,G是一个影响因素,H是另外一个影响因素。如果您的 F 比较贴近实际情况,也就是说估价函数贴近实际情况,总能(或在大部分情况下)给您最好的选择,那么您的算法是非常有效率的。
反之,就像选取路径的标准是天气如何一样,您的算法效率将不会那么的高。

以上的描述只能帮助您理解,而不是标准甚至正确的说法。

Dijkstra

在队列中,如果我们每次找到距离最短的一个点去更新其他点,当这个点出队第K次的时候,当前的距离就是到该点的第k短路。我们将这个点类推为重点,则得到,当终点出现第k次的时候,我们求得了从起点到终点的第K短路。

这个过程可以用Dijkstra实现。我们同时设置了这么一个估价函数

F = G  +  H G :该点到起点的距离H :该点到终点的距离

每一次进行更新距离时,同时更新估价函数F,最后使用堆或优先队列维护。事实上,除了上述这种估价函数的描述以外,还有很多其他的写法,他们的本质上都是一样的。

代码如下

//K-th_Road.cpp////Glasses#include <map>#include <queue>#include <cmath>#include <vector>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define LL int#define MAXN 100005#define MOD 1000000007#define INF 0x7f7f7f7f#define FOR(i,a,b) for(LL i = (a), i##end = (b); i <= i##end; ++i)#define ROF(i,a,b) for(LL i = (a), i##begin = (b); i >= i##begin; --i)#define put0(str) memset( (str) , 0, sizeof( (str) ));#define putinf(str) memset( (str) , INF ,sizeof((str)));#define output(a) printf("%d\n",(a));#define input(a) scanf("%d",&(a));LL read(){      LL x=0,tag=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')tag=-1;ch=getchar();}    while(ch>='0' && ch<='9')x=x*10+ch-'0',ch=getchar();      return x*tag;}struct k_th{    struct Node    {        LL x,f,h;        Node(){}        Node(LL a,LL b,LL c) : x(a),f(b),h(c){}        bool operator < (const Node& rhs) const        {            if(h==rhs.h)return f>rhs.f;            return h>rhs.h;        }    };    struct Edge    {        LL to,nxt,w;        Edge(){}        Edge(LL a,LL b,LL c):to(a),nxt(b),w(c){}    };    Edge edges[MAXN],redges[MAXN];    LL n,cnte,rcnte,k;    LL dis[1010],vis[1010],rhead[1010],head[1010];    void init(LL inn,LL ink)    {        this->n=inn;this->k=ink+1;cnte=rcnte=0;        put0(head);    }    void add_edge(LL a,LL b,LL c)    {        edges[++cnte]=Edge(b,head[a],c);head[a]=cnte;        redges[++rcnte]=Edge(a,rhead[b],c);rhead[b]=rcnte;    }    queue<LL> q;    void spfa(LL st)    {        while(!q.empty())q.pop();        put0(vis);putinf(dis);        q.push(st);        dis[st]=0;vis[st]=1;        while(!q.empty())        {            LL x=q.front();q.pop();vis[x]=0;                for(LL i=rhead[x];i;i=redges[i].nxt)            {                if(dis[redges[i].to]>dis[x]+redges[i].w)                {                    dis[redges[i].to]=dis[x]+redges[i].w;                    if(!vis[redges[i].to])                    {                        vis[redges[i].to]=1;                        q.push(redges[i].to);                    }                }            }        }    }    priority_queue<Node> qq;    LL Astar(LL st,LL ed)    {        spfa(ed);        put0(vis);        if(dis[st]==INF)return -1;        if(st==ed)k++;        qq.push(Node(st,0,dis[st]));        while(!qq.empty())        {            Node x=qq.top();qq.pop();            ++vis[x.x];            if(vis[x.x]>k)continue;            if(vis[ed]==k)return x.f;            for( LL i=head[x.x];i;i=edges[i].nxt )            {                LL t1=x.f+edges[i].w;                LL t2=t1+dis[edges[i].to];                qq.push( Node(edges[i].to,t1,t2) );            }        }        return -1;    }}e;

错误是我的,请让我吃掉:(

1 0
原创粉丝点击