• 蒟蒻林荫小复习——K短路的A*解法


    看标题都知道讲的是什么,但为什么特指是A*关于K短路的解法呢?

    因为林荫不会其他的。

    能看到这篇博客的估计也都知道K短路和A*分别是什么了吧,下面只介绍一下估价函数

    由于林荫并没有经过学术训练,所以一下关于A*的理解均为感性,仅可作为OIer速成知识点时的一点资料,

    切莫作为算法学术依据。

    先思考一下,对于任意一条K短路,是不是均可写成由一部分最短路和一部分其他路径组成,而且这两部分路径还有且仅有一个公共点。

    说明:1.任何一条路径都可以视为由其他到终点的路径和终点到终点的最短路组成

       2.哪怕前面的路径上有环,最短路也一定和其他的路径在环的出点上相连。因为一旦最短路和路径上其他点相交,就代表该最短路上有环,那么这条路径就不是最短路。

    好的,下面引入概念:估价函数!

    实际上没啥特别的,就一个公式 F(x)=G(x)+H(x),F(x)是该路线的期望花费,G(x)是从起点到当前点的花费,H(x)是当前点到终点的最优花费。

    那么,我们在求解的时候是不是有个大致思路了?

    K值越小的路径的X点离起点越近(大概就这个意思,也可以认为越接近最短路的路线所使用的最短路越多)

    那么我们是否可以考虑先将H处理出来(建反图,求单源最短路),然后维护一个优先队列,队列里面保存一个Pair(F(x)和x点),那么我们每次根据F(x)的值决定下一个执行的点,如果x已经是终点了,就该统计答案统计答案,该返回返回,否则针对x计算出每一个相连接的点to,求出F(to)后压入队列,直到完成K个路径或者发现当前最短的一条路径已经不满足需求。

    至于如何确定第K短路就知道了吧(由于有优先队列,第一个出来的一定是最短,第二个一定是次短,第三个一定是3TH)。

    下面放个代码吧,例题COGS3227

    严格来说这个并不算K短路,而是给定特殊限制,求满足条件的路径

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    vector<pair<int,int> > b[1001],fb[1001];
    int vis[1001],dis[1001];
    int n,m,a1,a2,a3,S,F,ans,MX,T;
    void DIJ()
    {
        memset(dis,0x3f3f3f3f,sizeof(dis));
        memset(vis,0,sizeof(vis));
        priority_queue<pair<int,int> > q; 
        dis[F]=0;
        q.push(make_pair(0,F));
        while(q.size())
        {
            int u=q.top().second;
            q.pop();
            if(vis[u])
                continue;
            vis[u]=1;
            for(int i=0;i<fb[u].size();i++)
            {
                int to=fb[u][i].first;
                if(dis[to]>dis[u]+fb[u][i].second)
                {
                    dis[to]=dis[u]+fb[u][i].second;
                    q.push(make_pair(-dis[to],to));
                }
            }
        }
    }
    void ASTAR()
    {
        priority_queue<pair<int,int> > q;
        q.push(make_pair(-dis[S],S));
        while(q.size())
        {
            int u=q.top().second;
            int v=q.top().first;
            q.pop();
            int dist=-v-dis[u];//实际上从起点到u的距离
            if(dist>MX)
                continue;
            if(u==F)
            {
                if(dist<=MX)
                {
                    ans++;
                }
                else
                    return;
            } 
            for(int i=0;i<b[u].size();i++)
            {
                int to=b[u][i].first;
                q.push(make_pair(-(dist+b[u][i].second+dis[to]),to));
            }
        }
    }
    int LINYIN()
    {
        ans=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            b[i].clear();
            fb[i].clear();
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&a1,&a2,&a3);
            fb[a2].push_back(make_pair(a1,a3));
            b[a1].push_back(make_pair(a2,a3));
        }
        scanf("%d%d",&S,&F);
        DIJ();
        MX=dis[S]+1;
        ASTAR();
        printf("%d
    ",ans);
        return 0;
    }
    int LWH()
    {
        freopen("sightseeing.in","r",stdin);
        freopen("sightseeing.out","w",stdout);
        scanf("%d",&T);
        while(T--)
        {
            LINYIN();
        }
        return 0;
    }
    int MYLOVE=LWH();
    int main()
    {
        ;
    }

    完结撒花!!!

  • 相关阅读:
    中国年薪 ¥30 万和美国年薪$ 10 万的生活水平异同
    汽车之家CMDB设计思路 – 汽车之家运维团队博客
    平民软件 | 中间件
    FIT2CLOUD
    ZeroBrane Studio
    新炬网络-领先数据资产运营商 | 数据资产管理 | 数据库运维 | 自动化运维
    中国(南京)软件开发者大会
    夏仲璞 | 全球软件开发大会北京站2016
    Nginx下流量拦截算法 | 夏日小草
    docker~dockertoolbox的加速器
  • 原文地址:https://www.cnblogs.com/XLINYIN/p/11828725.html
Copyright © 2020-2023  润新知