A*算法在最短路問題的應用及其使用舉例


 

 

 

1 A*算法

    A*算法在人工智能中是一種典型的啟發式搜索算法,啟發中的估價是用估價函數表示的:

第K最短路-A*啟發式搜索

其中f(n)是節點n的估價函數,g(n)表示實際狀態空間中從初始節點到n節點的實際代價,h(n)是從n到目標節點最佳路徑的估計代價。另外定義h'(n)為n到目標節點最佳路徑的實際值。如果h'(n)≥h(n)則如果存在從初始狀態走到目標狀態的最小代價的解,那么用該估價函數搜索的算法就叫A*算法。

 

2 第K最短路的算法

    我們設源點為s,終點為t,我們設狀態f(i)的g(i)為從s走到節點i的實際距離,h(i)為從節點i到t的最短距離,從而滿足A*算法的要求,當第K次走到f(n-1)時表示此時的g(n-1)為第K最短路長度。C++代碼如下:()

CDOJ找的一道例題:(模板題)這里面用到SPFA算法(這是中國人創造的得意,用於求單源最短路的一種算法,關於SFPA時間復雜度的問題,,,不確定性,有時很大,有時很小,emmmm,貌似外國人不太認可,)

 

 

 

Time Limit: 10000 MS     Memory Limit: 256 MB

Submit Status

6·1即將來臨,游樂園推出了新的主題活動,雨過天晴,帆寶樂爺童心未泯,准備一探究竟。

興奮的他們一入園便和孩子們打成一片,不知不覺便走散了。

當他們意識到的時候,只能通過手機來確認對方的位置。

他們當然想盡快找到對方,然而由於孩子們實在是太多,只能選擇距離稍遠的但是游客稀少的路會合。

帆寶希望找到第kk短的路徑,這條路徑是他認為的幸運路徑。

帆寶迫切地想知道該條路徑的長度,而樂於助人的你也一定會幫助她的。

Input

第一行三個整數n,m,kn,m,k,分別表示游樂園的景點數目、景點之間的道路數目以及路徑長度從小到大排列時希望選擇的序號。

第二行兩個整數S,TS,T,分別表示帆寶樂爺所在景點的編號。

接下來mm行,每行三個整數u,v,wu,v,w,表示編號為uu和vv的景點之間有一條長度為ww的單向通路。

1≤n≤1000,0≤m≤100000,1≤k≤1000,1≤S,T,u,v≤N,1≤w≤1001≤n≤1000,0≤m≤100000,1≤k≤1000,1≤S,T,u,v≤N,1≤w≤100

Output

第一行一個整數xx,表示所選路徑的長度

無解輸出−1−1

Sample input and output

Sample Input Sample Output
3 3 2
1 2
1 2 2
1 3 4
3 2 1
5

 

 

題意:給你起點,終點以及要求的第K短路;

題解:首先將有向圖以終點T為起點,計算出T到每一個邊的最短距離(到第i條邊dis[i]),

然后建立一個優先隊列,從優先隊列中彈出f(p)最小的點p,如果p就是T,則T的次數加一。如果當前次數等於K則當前路即為地K小

的路,,否則,,便利每一個p 所連的邊,將其擴張出的到p臨接點的信息加入到優先隊列中;

 

AC代碼:

  1 #include <bits/stdc++.h>
  2 #define INF 0x3f3f3f3f
  3 using namespace std;
  4 const int AX = 1e5+66;
  5 const int MAXN = 1e3+66;
  6 int n,m,k;
  7 int s,t;
  8 int tot;
  9 int retot;
 10 struct edge{
 11     int to,w;
 12     int next1;
 13 }G[AX],RG[AX];
 14 
 15 struct Node{
 16     int v;
 17     int f,h,g;
 18     bool operator < (const Node &a) const{ return f==a.f? g>a.g : f>a.f; }
 19 };
 20 
 21 
 22 int dis[MAXN];
 23 int head[MAXN];
 24 int rehead[AX];
 25 int vis[MAXN];
 26 
 27 void add_edge(int u,int v,int c)
 28 {
 29     G[tot].to=v;
 30     G[tot].w=c;
 31     G[tot].next1=head[u];
 32     head[u]=tot++;
 33 
 34     RG[retot].to=u;
 35     RG[retot].w=c;
 36     RG[retot].next1=rehead[v];
 37     rehead[v]=retot++;
 38 }
 39 void SPFA()
 40 {
 41     for(int i=1;i<=n;i++) dis[i]=INF;
 42     dis[t]=0;
 43     queue<int> Q;
 44     Q.push(t);
 45     while(!Q.empty())
 46 {
 47         int u=Q.front();
 48         Q.pop();
 49         for(int i=rehead[u];i!=-1;i=RG[i].next1)
 50 {
 51             int v=RG[i].to ;
 52             int w=RG[i].w ;
 53             if(dis[v]>dis[u]+w)
 54 {
 55                 dis[v]=dis[u]+w;
 56                 Q.push(v);
 57             }
 58         }
 59     }   
 60 }
 61 
 62 int Astar(Node a)
 63 {
 64     memset(vis,0,sizeof(vis));
 65     if(dis[s]==INF) return -1;//如果沒有與S相連的點 
 66     if(s==t) k++;
 67     priority_queue<Node> Q;
 68     Q.push(a);
 69     while(!Q.empty())
 70 {
 71         Node tmp=Q.top();
 72         Q.pop();
 73         int v=tmp.v;
 74         vis[v]++;
 75         if(vis[t]==k) return tmp.g;
 76         for(int i=head[v];i!=-1;i=G[i].next1)
 77 {
 78             Node p;
 79             p.v=G[i].to;
 80             p.h=dis[G[i].to];
 81             p.g=tmp.g+G[i].w;
 82             p.f=p.g+p.h;
 83             Q.push(p);
 84         }
 85     }
 86     return -1;
 87 }
 88 
 89 int main()
 90 {
 91     tot=0;
 92     retot=0;
 93     memset(head,-1,sizeof head);
 94     memset(rehead,-1,sizeof rehead);
 95     scanf("%d%d%d",&n,&m,&k);
 96     scanf("%d%d",&s,&t);
 97     int x,y,w;
 98     for(int i=0;i<m;i++)
 99 {
100         scanf("%d%d%d",&x,&y,&w);
101         add_edge(x,y,w);
102     }
103     SPFA();
104     Node a;
105     a.v=s;
106     a.g=0;
107     a.h=dis[s];
108     a.f=a.g+a.h;
109     int g=Astar(a);
110     printf("%d\n",g);
111     return 0 ;
112 }
View Code

 

后面我還會更新出 關於啟發式搜索的講解,以及Dijkstra,,SPFA,Folyd這三種關於不同最短路問題講解及例題分析。

越努力,越幸運!    加油!!!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM