K短路(A*)

作者: 雨落八千里 | 来源:发表于2019-08-14 21:51 被阅读9次

在BFS搜索中,始点S第一次到达目标点E的路径是最短的,那再搜索中第k次到达目标点E就是第K短了。但这样很容易超时。因此介绍一种搜索算法A* (启发式搜索)

A*简单的说,它可以用公式表示为f(x) = g(x) + h(x),其中,f(x)是从始点s经由节点xe的估价函数,g(x)是在状态空间中从x到n的实际代价,h(x)是从xe的最佳路径估计代价。在设计中,要保证h(x)<= h^*(x) (xe的实际代价)。这一点很重要,h(x)越接近真实值,速度越快。

  • h(x) <= h ^* (x)h^*(x)为实际问题的代价值)

  • h(x)==0就是Dijkstra,g(x)==0就是BFS

  • g(x)表示从初始结点s到任意结点x的代价,h(x)表示从结点x到目标点e的启发式评估代价

启发式函数可以控制A*的行为:

  1. 如果h(x)==0,则只有g(x)起作用,此时A*演变成Dijkstra算法,这保证能找到最短路径。
  2. 如果h(x)经常都比从x移动到目标的实际代价小(或者相等),则A*保证能找到一条最短路径。h(x)越小,A*扩展的结点越多,运行就得越慢。
  3. 如果h(x)精确地等于从x移动到目标的代价,则A*将会仅仅寻找最佳路径而不扩展别的任何结点,这会运行得非常快。尽管这不可能在所有情况下发生,你仍可以在一些特殊情况下让它们精确地相等(指让h(x)精确地等于实际值)。只要提供完美的信息,A*会运行得很完美,认识这一点很好。
  4. 如果h(x)有时比从x移动到目标的实际代价高,则A*不能保证找到一条最短路径,但它运行得更快。
  5. 如果h(x)g(x)大很多,则只有h(x)起作用,A*演变成BFS算法。

K短路中f(x)x节点的过估价函数,则 f(x) = g(x) + h(x); h(x)就是我们所说的‘启发式函数’h(x)是节点x到目标点e的最小距离,
g(x)表示始点s到节点x的距离
1.将有向图的所有边反向,以原终点e为源点,求解e到所有点的最短距离,即 h(x);

  1. 新建一个优先队列,将源点s加入到队列中,队列中维护的是估价函数的值;
  2. 从优先级队列中弹出 f(x)最小的点 x,如果点x就是e,则计算e出队的次数;
    如果当前为 e 的第 k次出队,则当前路径的长度就是 se 的第k 短路的长度,算法结束;
    否则遍历与x相连的所有的边,将扩展出的到x的邻接点信息加入到优先级队列;

Remmarguts' Date

#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
const int M=1e5+100;
int headz[M],cntz;//正向存图
int headf[M],cntf;//反向存图
struct node
{
    int v,w,nxt;
} edgez[M],edgef[M];
int dis[10010];//h(x)
int vis[10010];
struct mat
{
    int v;
    int w;
    friend bool operator <(const mat x,const mat y)
    {
        return x.w+dis[x.v]>y.w+dis[y.v];//按照g(x)+h(x)<g(y)+h(y)
    }
} now,nxt;
void init( )
{
    memset(headz,-1,sizeof(headz));
    memset(headf,-1,sizeof(headf));
    cntz=cntf=0;
}
void addz(int x,int y,int w)
{
    edgez[++cntz].nxt=headz[x];
    edgez[cntz].v=y;
    edgez[cntz].w=w;
    headz[x]=cntz;
}
void addf(int x,int y,int w)//反向存图
{
    edgef[++cntf].nxt=headf[x];
    edgef[cntf].v=y;
    edgef[cntf].w=w;
    headf[x]=cntf;
}
void Dijkstra(int x)//反向遍历 求出终点到各个节点的最小距离
{
    memset(vis,0,sizeof(vis));
    memset(dis,INF,sizeof(dis));
    dis[x]=0;
    priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >qu;
    qu.push(make_pair(0,x));
    while(!qu.empty( ))
    {
        int u=qu.top().second;
        qu.pop( );
        if(!vis[u])
        {
            vis[u]=1;
            for(int i=headf[u]; i!=-1; i=edgef[i].nxt)
            {
                int v=edgef[i].v;
                if(dis[v]>dis[u]+edgef[i].w)
                {
                    dis[v]=dis[u]+edgef[i].w;
                    qu.push(make_pair(dis[v],v));
                }
            }
        }
    }
}
int Astar(int x,int y,int k)//正向遍历A*求出第K短路
{
    if(dis[x]==INF)
    {
        return -1;
    }
    int cnt=0;
    priority_queue<mat>qu;
    now.v=x;
    now.w=0;
    qu.push(now);
    while(!qu.empty( ))
    {
        now=qu.top( );
        qu.pop( );
        if(now.v==y)
        {
            cnt++;
            if(cnt==k)
            {
                return now.w;
            }
        }
        for(int i=headz[now.v]; i!=-1; i=edgez[i].nxt)
        {
            int v=edgez[i].v;
            nxt.v=v;
            nxt.w=edgez[i].w+now.w;
            qu.push(nxt);
        }
    }
    return -1;
}
int main( )
{
    int n,m,k,x,y,w;
    init( );
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; i++)
    {
        scanf("%d%d%d",&x,&y,&w);
        addz(x,y,w);
        addf(y,x,w);
    }
    scanf("%d%d%d",&x,&y,&k);
    Dijkstra(y);
    // for(int i=1;i<=n;i++)
    // {
    //     cout<<dis[i]<<" ";
    // }
    // cout<<endl;
    if(x==y)
    {
        k++;
    }
    int ans=Astar(x,y,k);
    cout<<ans<<endl;
    return 0;
}

相关文章

  • K短路(A*)

    在BFS搜索中,始点S第一次到达目标点E的路径是最短的,那再搜索中第k次到达目标点E就是第K短了。但这样很容易超时...

  • Yen的K条最短路径算法(KSP)

    一、问题介绍 1.求K条最短路径的必要性 最短路径问题分为: 单源最短路径 所有顶点对间的最短路径 共同的缺陷:这...

  • 图论---第k短路

    poj2249 A*算法 来自百度百科A* 算法,A* (A-Star)算法是一种静态路网中求解最短路径最有效的直...

  • (任意两点间最短路)Floyd-Warshall算法

    Floyd-Warshall算法使用DP方法来求解任意两点间的最短路问题。i到j的最短路分正好经过顶点k一次和完全...

  • poj --- 1724 最短路变形 Dij + 优先队列

    题目链接 题意:要从1到N的最短路并且每一条路上有对应的花费要求,总花费不能大于给定的一个值K,输出最短路径的长度...

  • Floyed

    path k 数组中保存的是最短路径经过的顶点,路径的特点是对于任意的顶点 i j,中间经过的顶点号不超过k例如p...

  • floyd算法解析

    floyd算法可求得多源点间的最短路径算法使用动态规划求解: 状态转移方程 dp[i][j][k]=min(dp[...

  • 记录一个只有五行的最短路径求解算法——FloydWarshall

    核心思想 结合动态规划思想,通过不断迭代中转点k后两点i、j之间的最短路径来求解。 代码及注释

  • 设计中的短路电流的校核

    短路电电流 一)为什么计算最大短路电流?为什么计算最小短路电流? 目的:测试对于短路计算意义的理解 答案:计算最大...

  • 遍历 最短路径 1.单源最短路 有权图-Dijkstra 多源头最短路-Floyd算法 —————————————...

网友评论

    本文标题:K短路(A*)

    本文链接:https://www.haomeiwen.com/subject/agunjctx.html