A*模板(求K短路)(POJ2449)

A*是bfs的优化,IDA*是dfs的优化

A*算法: 为启发式算法中很重要的一种,被广泛应用在最优路径求解和一些策略设计的问题中。而A*算法最为核心的部分,就在于它的一个估值函数的设计上:
f(n)=g(n)+h(n) 其中f(n)是每个可能试探点的估值,它有两部分组成:一部分为g(n),它表示从起始搜索点到当前点的代价(通常用某结点在搜索树中的深度来表示)。另一部分,即h(n),它表示启发式搜索中最为重要的一部分,即当前结点到目标结点的估值,h(n)设计的好坏,直接影响着具有此种启发式函数的启发式算法的是否能称为A*算法。


题目(代码和原题稍微不同):
链接:POJ2449
第一行为n个点,m条边,求第k短路。
接下来m行,每行3个数,代表起点、终点、边权。

输出第k短路的路径长度。

解法:

K短路的定义:假设从1出发,有M条长度不同的路径可以到达点N,则K短路就是这M条路径中第K小的路径长度。 以上所述,设f[n]为最终所求,则f(n)=g(n)+h(n);h(n)就是我们所说的‘启发式函数’,表示为重点t到其余一点p的路径长度,g(n)表示g当前从s到p所走的路径的长度。
即:估价函数=当前值+当前位置到终点的距离

Solution:
(1)将有向图的所有边反向,以原终点t为源点,求解t到所有点的最短距离;
(2)新建一个优先队列,将源点s加入到队列中;
(3)从优先级队列中弹出f(p)最小的点p,如果点p就是t,则计算t出队的次数;
如果当前为t的第k次出队,则当前路径的长度就是s到t的第k短路的长度,算法结束;
否则遍历与p相连的所有的边,将扩展出的到p的邻接点信息加入到优先级队列;

代码如下:

#include<cstdio>
#include<vector>
#include<queue>
using namespace std;

const int inf = 999999999;
const int maxn = 500000 + 5;
int n, m, k, s, t;

struct edge {
    int v, w;
};
vector<vector<edge>>a, b;
vector<int>dis(maxn, inf);
vector<bool>flag(maxn, false);

//f(n)=g(n)+h(n)
//估价函数=当前值+当前位置到终点的距离
struct node {
    int id;///当前节点编号
    int f;//f表示经过当前节点的最短路
    int g;//g表示S->当前节点的最短路
    node(int id = 0, int f = 0, int g = 0) :id(id), f(f), g(g) {}
    bool operator <(const node &a)const {//估价函数值大或者距初始点最长的结点优先级高
        if (f == a.f) return g>a.g;
        return f>a.f;
    }
};

void add_edge(int u, int v, int w) {
    edge tmp;
    tmp.v = u; tmp.w = w; a[v].push_back(tmp);
    tmp.v = v; tmp.w = w; b[u].push_back(tmp);
}

void spfa(int s) {
    queue<int>q;
    q.push(s);
    dis[s] = 0; flag[s] = true;
    while (!q.empty()) {
        int u = q.front(); q.pop(); flag[u] = false;
        for (int i = 0; i < a[u].size(); i++) {//扫描所有邻接点
            if (dis[a[u][i].v] > dis[u] + a[u][i].w) {
                dis[a[u][i].v] = dis[u] + a[u][i].w;
                if (!flag[a[u][i].v]) {
                    q.push(a[u][i].v);
                    flag[a[u][i].v] = true;
                }
            }
        }
    }
}

void Astar(int s, int t) {
    if (s == t)k++;//没有这句会T
    if (dis[s] == inf){ printf("-1
"); return; }//没有这句会T
    priority_queue<node>q;
    q.push(node(s, 0, 0));
    int cnt = 0;
    while (!q.empty()) {
        node h = q.top(); q.pop();
        if (h.id == t) {
            if (++cnt == k) {
                printf("%d", h.f);//返回第k短路
                return;
            }
        }
        for (int i = 0; i < b[h.id].size(); i++) {
            q.push(node(b[h.id][i].v, h.g + b[h.id][i].w + dis[b[h.id][i].v], h.g + b[h.id][i].w));
        }
    }
    printf("-1
"); return;
}

int main() {
    a.resize(maxn);
    b.resize(maxn);
    scanf("%d%d%d", &n, &m, &k);
    scanf("%d%d", &s, &t);
    int u, v, w;
    for (int i = 0; i < m; i++) {
        scanf("%d%d%d", &u, &v, &w);
        add_edge(u, v, w);
    }
    spfa(t);
    Astar(s, t);
    return 0;
}
原文地址:https://www.cnblogs.com/romaLzhih/p/9489817.html