1. 程式人生 > >牛跑步

牛跑步

efi str tar int string 大於 生生 clu ...

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$的高度. 地點$N$是$Bessie$的牛棚;地點$1$是池塘.

很快, $Bessie$厭倦了一直走同一條路.所以她想走不同的路,更明確地講,她想找出$K (1 <= K <= 100)$條不同的路經.為了避免過度勞累,她想使這$K$條路徑為最短的$K$條路徑.

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

題目名稱: cowjog

輸入格式:

  • 第$1$行: 3個數: $N,M,K$
  • 第$2..M+1$行: 第 $i+1 $行包含3個數 $X_i, Y_i,D_i$, 表示一條下坡的路.

樣例輸入 (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)$

【思路】

Astar求k短路

【code】

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define road 10000+10
#define node 1000+10
struct Edge
{
    int x,y,z,next;
    Edge(int x=0,int y=0,int z=0,int next=0):
        x(x),y(y),z(z),next(next){}
}edge[road];
struct date
{
    int x,g,h;
 bool operator < (const date &a) const
    {
        return g+h>a.g+a.h;
    }
};
int nl,m,k,x,y,z,sumedge,s,e,size;
int head[node],ans[100+10],dis[node],cnt[node];
bool vis[node];
int add(int x,int y,int z)
{
    edge[++sumedge]=Edge(x,y,z,head[x]);
    return head[x]=sumedge;
}
void spfa()
{
    queue <int> q;
    memset(dis,127/3,sizeof(dis));
    dis[s]=0;vis[s]=1;q.push(s);    
    while(!q.empty())
    {
        int now=q.front();q.pop();
        vis[now]=0;
        for(int i=head[now];i;i=edge[i].next)
        {
            int to=edge[i].y;
            if(dis[to]>dis[now]+edge[i].z)
            {
                dis[to]=dis[now]+edge[i].z;
                if(!vis[to])
                {
                    vis[to]=1;
                    q.push(to);
                }
            }
        }
    }
}
void Astar()
{
    priority_queue <date> qq;
    qq.push((date){e,0,dis[e]});
    while(!qq.empty())
    {
        date nn=qq.top();qq.pop();
        ++cnt[nn.x];
        if(cnt[nn.x]>k)continue;
        if(nn.x==s){
            ans[++size]=nn.g;
        }
        if(cnt[s]==k){
         return;
        }
        for(int i=head[nn.x];i;i=edge[i].next)
        {
            qq.push( (date){edge[i].y,nn.g+edge[i].z,dis[edge[i].y]});
        
        }
    }
    return;
}
int main()
{
    freopen("cowjog.in ","r",stdin);
    freopen("cowjog.out","w",stdout);
    scanf("%d%d%d",&nl,&m,&k);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
    }
    s=1;e=nl;
    spfa();
    memset(ans,-1,sizeof(ans));
    Astar();
    for(int i=1;i<=k;i++)
    printf("%d\n",ans[i]);
    return 0;
 } 

【反思】

spfa出隊列時vis數組忘記清0......還有我忘記把第一個元素加入隊列......

還有我明明輸出是對的硬生生的爆0....技術分享

牛跑步