• 【图论】A*算法



    用得不多,就不讲那么详细了


    功能实现

    A*算法最主要的部分就是它的估价函数(f(i)=g(i)+h(i))

    (g(i))为到达某点已经付出的代价,(h(i))为该点到终点的估计代价

    则估价函数则为两者之和

    放入优先队列中,将会先处理估计总代价最小的状态,以取得(k)短路


    求从点(st)到点(ed)的第(k)短路的长度

    如上面估价函数所需要的,我们需要先求出(h(i)),即预处理出图中每个点到终点(ed)的估计代价(最短路径)

    对于多起点同终点类型问题,可以将有向图中所有边全部取反,获得一张反向图,然后以(ed)为起点跑遍整张反向图求出最短路即可

    所以此时只需要跑一边SPFA求出(ed)到任意点的最短距离(dis[i]),即可当作正向图中的(h(i))

    然后便是Astar的主要部分

    建立一个新结构体(node)保存搜索过程中每一种状态({to,g(i),f(i)}),根据上述估价函数,重载运算符时将(f(i))作为主关键词,将(g(i))作为次关键词

    从小到大排序(放入小顶堆优先队列中),或从大到小排序(放入大顶堆优先队列中)

    以类似bfs的方法,从起点(st)开始搜索,以优先队列作为搜索队列

    每当搜索到一次(ed)点,就表明找到了一条最短路,直到第(k)次搜索到(ed)点时,便可以直接返回当前状态的(g(i))作为第(k)短路的代价

    若在队列为空前均没有返回,说明不存在第(k)短路



    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef pair<int,int> P;
    
    const int INF=0x3f3f3f3f;
    const int maxn=100050;
    
    struct node
    {
        int to,g,f;
        bool operator < (const node &r) const
        {
            if(r.f==f)
                return r.g<g;
            return r.f<f;
        } //从大到小排序,放入大顶堆内(使用时就会变成从小到大)
    };
    vector<P> G[maxn]; //正向图,{first,second}={to,cost}
    vector<P> IG[maxn]; //反向图
    bool inq[maxn];
    int dis[maxn]; //dis[i]为i到ed的最短路径
    
    void init(int n)
    {
        for(int i=1;i<=n;i++)
        {
            G[i].clear();
            IG[i].clear();
        }
    }
    
    void SPFA(int n,int st)
    {
        queue<int> que;
        for(int i=1;i<=n;i++)
        {
            dis[i]=INF;
            inq[i]=false;
        }
        dis[st]=0;
        inq[st]=true;
        que.push(st);
        while(!que.empty())
        {
            int cur=que.front();
            que.pop();
            inq[cur]=false;
            for(P &pd:IG[cur])
            {
                if(dis[pd.first]>dis[cur]+pd.second)
                {
                    dis[pd.first]=dis[cur]+pd.second;
                    if(!inq[pd.first])
                    {
                        inq[pd.first]=true;
                        que.push(pd.first);
                    }
                }
            }
        }
    }
    
    int AStar(int n,int st,int ed,int k)
    {
        priority_queue<node> pq;
        if(st==ed)
            k++;
        node tmp=node{st,0,dis[st]};
        int cnt=0;
        pq.push(tmp);
        while(!pq.empty())
        {
            node nd=pq.top();
            pq.pop();
            if(nd.to==ed)
                cnt++; //找到一条最短路
            if(cnt==k)
                return nd.g; //当前找到的是k短路
            for(P &pd:G[nd.to])
            {
                tmp.to=pd.first; //去往的节点
                tmp.g=nd.g+pd.second; //当前代价g
                tmp.f=tmp.g+dis[pd.first]; //估计代价f=g+h
                pq.push(tmp);
            }
        }
        return -1;
    }
    
    int main()
    {
        int n,m,u,v,c,st,ed,k;
        scanf("%d%d",&n,&m);
        init(n);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&c);
            G[u].push_back(P(v,c));
            IG[v].push_back(P(u,c));
        }
        scanf("%d%d%d",&st,&ed,&k);
        SPFA(n,ed);
        printf("%d
    ",AStar(n,st,ed,k));
        
        return 0;
    }
    

    实在没找到啥非常模板的模板题,略过——


  • 相关阅读:
    mono for android学习过程系列教程(6)
    mono for android学习过程系列教程(5)
    mono for android学习过程系列教程(4)
    mono for android学习过程系列教程(3)
    mono for android学习过程系列教程(2)
    mono for android学习过程系列教程(1)
    随笔索引
    中国大学MOOC中的后台文件传输
    知乎控件分享(一)
    知乎UWP 预览
  • 原文地址:https://www.cnblogs.com/stelayuri/p/13365068.html
Copyright © 2020-2023  润新知