码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 2499 A*求第K短路

时间:2015-09-02 00:03:55      阅读:207      评论:0      收藏:0      [点我收藏+]

标签:

DES就是给你一个图。然后给你起点和终点。问你从起点到终点的第K短路。

第一次接触A*算法。

技术分享
// 大概懂思路了。A*算法需要的估价函数里的两个函数、一个是起点到当前点的消耗。
//一个是当前点到目标点的估测消耗。所以需要用Dijstra或者Spfa求出目标点到所有点的最短路。
//然后就可以用A*算法来求了。
// 确实。学了位运算。链式表。

#include<cstdio>
#include<iostream>
#include<queue>
#include<string.h>
#define maxn 1005
#define maxm 200100
using namespace std;

struct Node{
  int v, c, n, nxt;
}Edge[maxm];

int head[maxn];
int tail[maxn];
int h[maxn];

struct Statement {
   int v, d, h;
   bool operator < (Statement a) const {
     return a.d+a.h<d+h;
   }
};

void addEdge (int u, int v, int c, int e)
{
    Edge[e<<1].v = v;
    Edge[e<<1].c = c;
    Edge[e<<1].nxt = head[u];
    head[u] = e<<1; // A*算法对周边的店扩展时按是从1到n;

    // 任意数|1相当于给这个数+1。
    Edge[e<<1|1].v = u;
    Edge[e<<1|1].c = c;
    Edge[e<<1|1].nxt = tail[v];
    tail[v] = e<<1|1; // Dijstra求最短路时、改为求t到其它所有节点的单源最短路
    return;
}

void Dijstra (int n, int s, int t)
{
    bool vis[maxn];
    memset(vis, 0, sizeof(vis));
    memset(h, 0x7F, sizeof(h));
    h[t] = 0;
    for (int i=1; i<=n; ++i) {
        int min = 0x7FFF;
        int k = -1;
        for (int j=1; j<=n; ++j) {
            if (vis[j] == false && min>h[j])
                min = h[j], k = j;
        }
        if (k == -1) break;
        vis[k] = true;
        for (int temp=tail[k]; temp != -1; temp=Edge[temp].nxt) {
            int v = Edge[temp].v;
            if (h[v] > h[k]+Edge[temp].c)
                h[v]=h[k]+Edge[temp].c;
        }
    }
}

int Astar_Kth (int n, int s, int t, int k)
{
    Statement cur, nxt;
    priority_queue<Statement>FstQ;

    int cnt[maxn];
    memset(cnt, 0, sizeof(cnt));
    cur.v = s; // 开启列表的第一个点、当前移动耗费和预估移动耗费。
    cur.d = 0;
    cur.h = h[s];

    FstQ.push(cur);

    while(!FstQ.empty()) {
        cur = FstQ.top();
        FstQ.pop();

        cnt[cur.v]++;  // cnt[] 表示当前节点被扩展了几次。如果大于k 显然不符合题意。
        if (cnt[cur.v] > k) continue;  // 某个节点的第X次扩展。就说明这是该节点的第X短路、。
        if (cnt[t] == k) return cur.d; // 如果目标节点刚好被扩展了k次。说明找到第K短路。结束寻路、

        for (int temp=head[cur.v]; temp!=-1; temp=Edge[temp].nxt) {
            int v = Edge[temp].v;
            nxt.d = cur.d + Edge[temp].c;
            nxt.v = v;
            nxt.h = h[v];
            FstQ.push(nxt);
        }
    }
    return -1;
}

int main()
{
    int n, m;
    while(scanf("%d %d", &n, &m) != EOF) {
        int u, v, c;
        memset(head, -1, sizeof(head));
        memset(tail, -1, sizeof(tail));

        for (int i=0; i<m; ++i) {
            scanf("%d %d %d", &u, &v, &c);
            addEdge(u, v, c, i);
        }

        int s, t, k;
        scanf("%d %d %d", &s, &t, &k);
        if (s == t) k++;
        Dijstra(n, s, t);
        printf("%d\n", Astar_Kth(n, s, t, k));
    }
    return 0;
}
View Code

 

POJ 2499 A*求第K短路

标签:

原文地址:http://www.cnblogs.com/icode-girl/p/4777002.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!