1. 程式人生 > >cogs 133. [USACO Mar08] 牛跑步 A*算法

cogs 133. [USACO Mar08] 牛跑步 A*算法

簡單 n-1 程序 每次 需要 ace 並排 blog -s

by  http://blog.csdn.net/jarily/article/details/8871968
/*
*算法引入: *在單源點最短路徑問題中,實際運用時還需知道最短路徑外,次短路或者第三短路; *即要知道多條最短路,並排出其長度增加的順序,即為K最短路問題; * *算法思想: *單源點最短路徑+高級搜索A*; *A*算法結合了啟發式方法和形式化方法; *啟發式方法通過充分利用圖給出的信息來動態地做出決定而使搜索次數大大降低; *形式化方法不利用圖給出的信息,而僅通過數學的形式分析; * *算法通過一個估價函數f(h)來估計圖中的當前點p到終點的距離,並由此決定它的搜索方向; *當這條路徑失敗時,它會嘗試其他路徑; *對於A*,估價函數=當前值+當前位置到終點的距離,即f(p)=g(p)+h(p),每次擴展估價函數值最小的一個; * *對於K短路算法來說,g(p)為當前從s到p所走的路徑的長度;h(p)為點p到t的最短路的長度; *f(p)的意義為從s按照當前路徑走到p後再走到終點t一共至少要走多遠; * *為了加速計算,h(p)需要在A*搜索之前進行預處理,只要將原圖的所有邊反向,再從終點t做一次單源點最短路徑就能得到每個點的h(p)了; * *算法步驟: *(1),將有向圖的所有邊反向,以原終點t為源點,求解t到所有點的最短距離; *(2),新建一個優先隊列,將源點s加入到隊列中; *(3),從優先級隊列中彈出f(p)最小的點p,如果點p就是t,則計算t出隊的次數; *如果當前為t的第k次出隊,則當前路徑的長度就是s到t的第k短路的長度,算法結束; *否則遍歷與p相連的所有的邊,將擴展出的到p的鄰接點信息加入到優先級隊列; * *算法測試: *http://www.cogs.pro/cogs/problem/problem.php?pid=133 * *題目大意: *求從s到t的第k短路的長度;
*/

133. [USACO Mar08] 牛跑步

★★★ 輸入文件:cowjog.in 輸出文件:cowjog.out 簡單對比
時間限制:1 s 內存限制:128 MB

Bessie準備用從牛棚跑到池塘的方法來鍛煉. 但是因為她懶,她只準備沿著下坡的路跑到池塘,然後走回牛棚.

Bessie也不想跑得太遠,所以她想走最短的路經. 農場上一共有M(1<=M<=10,000)條路,每條路連接兩個用1..N(1<=N<=1000)標號的地點. 更方便的是,如果X>Y,則地點X的高度大於地點Y的高度. 地點NBessie的牛棚;地點1是池塘.

很快, Bessie厭倦了一直走同一條路.所以她想走不同的路,更明確地講,她想找出K(1<=K<=100)

條不同的路經.為了避免過度勞累,她想使這K條路徑為最短的K條路徑.

請幫助Bessie找出這K條最短路經的長度.你的程序需要讀入農場的地圖, 一些從XiYi的路徑和它們的長度(Xi,Yi,Di). 所有(Xi,Yi,Di)滿足(1<=Yi<Xi;Yi<Xi<=N,1<=Di<=1,000,000).

題目名稱: cowjog

輸入格式:

  • 1行: 3個數: N,M,K
  • 2..M+1行: 第 i+1行包含3個數 Xi,Yi,Di, 表示一條下坡的路.

樣例輸入 (cowjog.in):

5 8 7
5 4 1
5 3 1
5 2 1
5 1 1
4 3 4
3 1 1
3 2 1
2 1 1

輸出格式:

  • 1..K行: 第i行包含第i最短路徑的長度,或?1如果這樣的路徑不存在.如果多條路徑有同樣的長度,請註意將這些長度逐一列出.

樣例輸出 (cowjog.out):

1
2
2
3
6
7
-1

輸出解釋:

路徑分別為(5?1),(5?3?1),(5?2?1),(5?3?2?1),(5?4?3?1),(5?4?3?2?1)

代碼:

/*
    k短路:
    建立反向圖,計算終點到起點的單源最短路,最後A*求解最短路 
    A*算法:
    新建一個優先隊列,將源點s加入到隊列中; 
    從優先級隊列中彈出估值函數f()最小的點p,如果點p就是t,則計算t出隊的次數;
    f(n)=g(n)+h(n)  g(n) 表示走到當前點的路程  
    h(n) 表示當前位置到終點的距離(在反向跑時已經計算出) 
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>

using namespace std;
const int N=10010;
const int INF=9999999;

int head[N],head2[N],disf[N],ans[N];
int now1=1,now2=1,n,m,k,x,y,z,js;
bool vis[N];
struct zheng{
    int u,v,w,nxt;
}Z[N];
struct fang{
    int u,v,w,nxt;
}F[N];
struct node{
    int start,wei,will;
}now,nxt,topp;

inline int read()  
{  
    int x=0,f=1;char ch=getchar();  
    while(ch<0 || ch>9) {if(ch==-) f=-1;ch=getchar();}  
    while(ch>=0 && ch<=9) {x=(x<<1)+(x<<3)+ch-0;ch=getchar();}  
    return x*f;   
} 

inline void add(int u,int v,int w)
{Z[now1].v=v;Z[now1].w=w;Z[now1].nxt=head[u];head[u]=now1++;}

inline void add2(int u,int v,int w)
{F[now2].v=v;F[now2].w=w;F[now2].nxt=head2[u];head2[u]=now2++;}

bool operator < (node a,node b)
{return a.will>b.will;}

inline void spfa(int start)
{
    for(int i=1;i<=n;i++)
        disf[i]=INF;
    disf[start]=0;vis[start]=1;
    queue<int>q;
    q.push(start);
    while(!q.empty())
    {
        int topp=q.front();
        q.pop();
        vis[topp]=0;
        for(int i=head2[topp];~i;i=F[i].nxt)
            if(disf[F[i].v]>disf[topp]+F[i].w)
            {
                disf[F[i].v]=disf[topp]+F[i].w;
                if(!vis[F[i].v])
                    vis[F[i].v]=1,
                    q.push(F[i].v);
            }
    }
}

inline void Astart(int start,int endd)
{
    if(disf[start]==INF||start==endd)return ;
    priority_queue<node>q;
    now.start=start;now.wei=0;now.will=disf[start];
    q.push(now);
    while(!q.empty())
    {
        topp=q.top();
        q.pop();
        if(topp.start==endd)
        {
            ans[++js]=topp.wei;
            if(js==k)return ;
        }
        for(int i=head[topp.start];~i;i=Z[i].nxt)
        {
            nxt.start=Z[i].v;nxt.wei=topp.wei+Z[i].w;
            nxt.will=nxt.wei+disf[Z[i].v];
            q.push(nxt);
        }
    }
}

int main()
{
    freopen("cowjog.in","r",stdin);
    freopen("cowjog.out","w",stdout);
    n=read();m=read();k=read(); 
    for(int i=1;i<=n;i++)head[i]=head2[i]=-1;
    for(int i=1;i<=m;i++) x=read(),y=read(),z=read(),add(x,y,z),add2(y,x,z);
    spfa(1);//反向邊的最短路 
    Astart(n,1);
    for(int i=1;i<=js;i++)printf("%d\n",ans[i]);
    for(int i=js+1;i<=k;i++)printf("-1\n");
    return 0;
}
/*
5 8 7
5 4 1
5 3 1
5 2 1
5 1 1
4 3 4
3 1 1
3 2 1
2 1 1
*/

cogs 133. [USACO Mar08] 牛跑步 A*算法