poj2449--A*算法求解k短路

今天想到了以前早就遺留下來的一個算法–A*算法,基本上,我對於A*只有過簡單的瞭解,卻從來沒有具體的寫過 A*,於是就有了今天的A*學習。

A*算法相比與其他的搜索來說,它多了一個估價函數而已。而估價函數在不同的題目中形式又不同,這正是A*難的地方啊~

對於此題:給出n個點,m條邊,可能又重邊,給定起點,終點,求k短路。

k短路是A*的一個最簡單的應用。
我們可以設計這樣的估價函數:
f(u)=g(u)+h(u).f來代表從s到t的總代價,g爲s到u的總代價,h是剩下路徑的總代價。於是我們可以從t跑一遍spfa,來求解出t到每個點的距離,然後將其加入優先隊列中,我們可以知道,k短路即優先隊列中第k個到達t的路徑。
注意:估價函數的估計代價一定比實際代價少,這樣才能是A*滿足條件。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define For(aa,bb,cc) for(int aa=bb;aa<=cc;++aa)
#define Set(aa,bb) memset(aa,bb,sizeof(aa))
using namespace std;
const int maxn=100010,maxm=1010,inf=0x3f3f3f3f;
int be[maxn],ne[maxn],to[maxn],w[maxn],e;
int revbe[maxn],revne[maxn],revto[maxn],revw[maxn],reve;
int dis[maxm];
bool vis[maxn];
int n,m,s,t,k;

struct Astar{
    int f,g,p;//f表示路程和,g表好已經走過的路程,h表示對應的點
    bool operator <(const Astar a)const{
        return f==a.f?g>a.g:f>a.f;
    }
};

void add(int x,int y,int z){
    ne[++e]=be[x],be[x]=e,to[e]=y,w[e]=z;
    revne[e]=revbe[y],revbe[y]=e,revto[e]=x,revw[e]=z;
}

void spfa(int node){
    For(i,1,n) dis[i]=inf,vis[i]=0;
    dis[node]=0;
    int q[maxn],f=0,l=0;
    q[++l]=node;vis[node]=1;
    while(f<l){
        int ls=q[++f];vis[ls]=0;
        for(int i=revbe[ls];i;i=revne[i]){
            int u=revto[i];
            if(dis[u]>dis[ls]+revw[i]){
                dis[u]=dis[ls]+revw[i];
                if(!vis[u]){
                    vis[u]=1;
                    q[++l]=u;
                }
            }
        }
    }
}

int A_star(int l,int r){
    if(dis[l]==inf) return -1;
    if(l==r) ++k;
    priority_queue<Astar>q;
    Astar now;
    now.g=0,now.p=l,now.f=dis[l];
    q.push(now);
    int sum=0;
    while(!q.empty()){
        Astar ls=q.top();q.pop();
        if(ls.p==r){
            ++sum;
            if(sum==k) return ls.g;
        }
        for(int i=be[ls.p];i;i=ne[i]){
            now.p=to[i];
            now.g=ls.g+w[i];
            now.f=now.g+dis[to[i]];
            q.push(now);
        }
    }
    return -1;
}

void work(){
    scanf("%d%d",&n,&m);
    For(i,1,m){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
    }
    scanf("%d%d%d",&s,&t,&k);
    spfa(t);
    printf("%d\n",A_star(s,t));
}

int main(){
#ifndef ONLINE_JUDGE 
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    work();
    return 0;
}
發佈了53 篇原創文章 · 獲贊 6 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章