【BZOJ1598】牛跑步 [A*搜索]

牛跑步

Time Limit: 10 Sec  Memory Limit: 162 MB
[Submit][Status][Discuss]

Description

  BESSIE准备用从牛棚跑到池塘的方法来锻炼.
  但是因为她懒,她只准备沿着下坡的路跑到池塘, 然后走回牛棚.
  BESSIE也不想跑得太远,所以她想走最短的路经.
  农场上一共有M 条路, 每条路连接两个用1..N标号的地点.
  更方便的是,如果X>Y,则地点X的高度大于地点Y的高度.
  地点N是BESSIE的牛棚;地点1是池塘.
  很快, BESSIE厌倦了一直走同一条路.所以她想走不同的路,更明确地讲,她想找出K条不同的路经.为了避免过度劳累,她想使这K条路经为最短的K条路经.
  请帮助BESSIE找出这K条最短路经的长度.
  你的程序需要读入农场的地图,一些从X_i到Y_i 的路经和它们的长度(X_i, Y_i, D_i).

Input

  第1行: 3个数: N, M, 和K
  第 2..M+1行: 第 i+1 行包含3个数 X_i, Y_i, 和 D_i, 表示一条下坡的路.

Output

  第1..K行: 第i行包含第i最短路经的长度,或-1如果这样的路经不存在.如果多条路经有同样的长度,请注意将这些长度逐一列出.

Sample Input

  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

Sample Output

  1
  2
  2
  3
  6
  7
  -1

HINT

  1 <= M <= 10,000, 1 <= N <= 1000, 1 <= K <= 100

Main idea

  给定一张图,输出1~k短路的距离。

Solution

  既然是求k短路,那我们使用A*搜索,先反向建图,记录终点到每一个点的最短路,然后把这个dist当做估价来跑A*即可。可以证明:第k次搜到的路即是k短路

Code

  1 #include<iostream>
  2 #include<string>
  3 #include<algorithm>
  4 #include<cstdio>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<cmath>
  8 #include<queue>
  9 using namespace std;
 10 typedef long long s64;
 11
 12 const int ONE = 2e6+5;
 13
 14 int n,m,k;
 15 int S,T;
 16 int dist[ONE],vis[ONE],Output[ONE],tou,wei;
 17 int next[ONE],first[ONE],go[ONE],w[ONE],tot;
 18 int Ans[ONE],num;
 19
 20 struct point
 21 {
 22         int x,y,z;
 23 }a[ONE];
 24
 25 struct power
 26 {
 27         int x,real,eva;
 28         bool operator <(const power &a) const
 29         {
 30             return a.real + a.eva < real + eva;
 31         }
 32 };
 33
 34 inline int get()
 35 {
 36         int res=1,Q=1;  char c;
 37         while( (c=getchar())<48 || c>57)
 38         if(c==‘-‘)Q=-1;
 39         if(Q) res=c-48;
 40         while((c=getchar())>=48 && c<=57)
 41         res=res*10+c-48;
 42         return res*Q;
 43 }
 44
 45 void Add(int u,int v,int z)
 46 {
 47         next[++tot]=first[u];   first[u]=tot;   go[tot]=v;  w[tot]=z;
 48 }
 49
 50 void SPFA(int x)
 51 {
 52         int q[10000001];
 53         memset(dist,63,sizeof(dist));
 54         tou = 0; wei = 1;
 55         vis[x] = 1; dist[x] = 0; q[1] = x;
 56         while(tou < wei)
 57         {
 58             int u = q[++tou];
 59             for(int e=first[u];e;e=next[e])
 60             {
 61                 int v = go[e];
 62                 if(dist[v] > dist[u] + w[e])
 63                 {
 64                     dist[v] = dist[u] + w[e];
 65                     if(!vis[v]) vis[v] = 1, q[++wei] = v;
 66                 }
 67             }
 68             vis[u] = 0;
 69         }
 70 }
 71
 72 void Astar()
 73 {
 74         priority_queue <power> q;
 75         q.push( (power){S, 0, dist[S]} );
 76         while(!q.empty())
 77         {
 78             power u = q.top();  q.pop();
 79             if(u.x == T) Ans[++num] = u.real;
 80             if(++Output[u.x] > k) continue;
 81             if(Output[T] == k) return;
 82             for(int e=first[u.x]; e; e=next[e])
 83             {
 84                 int v=go[e];
 85                 q.push( (power){v, u.real+w[e], dist[v]} );
 86             }
 87         }
 88 }
 89
 90 int main()
 91 {
 92         n=get();    m=get();    k=get();
 93         S=n,    T=1;
 94         for(int i=1;i<=m;i++)
 95         {
 96             a[i].x=get();   a[i].y=get();   a[i].z=get();
 97             Add(a[i].y, a[i].x, a[i].z);
 98         }
 99         SPFA(T);
100
101         memset(first,0,sizeof(first));  tot=0;
102         for(int i=1;i<=m;i++) Add(a[i].x,a[i].y,a[i].z);
103
104         Astar();
105
106         for(int i=1;i<=k;i++)
107             printf("%d\n",Ans[i]!=0?Ans[i]:-1);
108
109 }

时间: 2024-11-03 05:43:12

【BZOJ1598】牛跑步 [A*搜索]的相关文章

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

by http://blog.csdn.net/jarily/article/details/8871968/* *算法引入: *在单源点最短路径问题中,实际运用时还需知道最短路径外,次短路或者第三短路; *即要知道多条最短路,并排出其长度增加的顺序,即为K最短路问题; * *算法思想: *单源点最短路径+高级搜索A*; *A*算法结合了启发式方法和形式化方法; *启发式方法通过充分利用图给出的信息来动态地做出决定而使搜索次数大大降低; *形式化方法不利用图给出的信息,而仅通过数学的形式分析;

牛跑步

133. [USACO Mar08] 牛跑步 ★★★   输入文件:cowjog.in   输出文件:cowjog.out   简单对比时间限制:1 s   内存限制:128 MB $Bessie$准备用从牛棚跑到池塘的方法来锻炼. 但是因为她懒,她只准备沿着下坡的路跑到池塘,然后走回牛棚. $Bessie$也不想跑得太远,所以她想走最短的路经. 农场上一共有$M (1 <= M <= 10,000)$条路,每条路连接两个用$1..N(1 <= N <= 1000)$标号的地点.

bzoj 1598: [Usaco2008 Mar]牛跑步 -- 第k短路,A*

1598: [Usaco2008 Mar]牛跑步 Time Limit: 10 Sec  Memory Limit: 162 MB Description BESSIE准备用从牛棚跑到池塘的方法来锻炼. 但是因为她懒,她只准备沿着下坡的路跑到池塘, 然后走回牛棚. BESSIE也不想跑得太远,所以她想走最短的路经. 农场上一共有M (1 <= M <= 10,000)条路, 每条路连接两个用1..N(1 <= N <= 1000)标号的地点. 更方便的是,如果X>Y,则地点X

[USACO Mar08] 牛跑步 --k短路

[USACO Mar08] 牛跑步 Bessie准备用从牛棚跑到池塘的方法来锻炼. 但是因为她懒,她只准备沿着下坡的路跑到池塘,然后走回牛棚. Bessie也不想跑得太远,所以她想走最短的路经. 农场上一共有M(1<=M<=10,000)条路,每条路连接两个用1..N(1<=N<=1000)标号的地点. 更方便的是,如果X>Y,则地点X的高度大于地点Y的高度. 地点N是Bessie的牛棚;地点1是池塘. 很快, Bessie厌倦了一直走同一条路.所以她想走不同的路,更明确地讲

BZOJ1598: [Usaco2008 Mar]牛跑步

传送门 K短路,普遍的算法是采用AStar求解,先建立反向边跑一遍dij,或者spfa什么的.跑出反向边的距离就可以看为估价函数中的$h()$.设$dist$为当前已经走过的距离,那么$f(node)=dist+h(son)$,然后跑一遍AStar,根据一些莫名其妙的东西可以得到第$i$次出栈的即为第$i$短路. //BZOJ 1598 //by Cydiater //2016.10.25 #include <iostream> #include <cstring> #includ

从地球到月球 蒙牛“跑步”助推大健康战略

4月23日,在"航天品质 健康中国"的大主题下,蒙牛联合阿里体育发起"十城太空跑"活动,以刚刚成功发射"天舟一号"的航天城文昌为主会场,与武汉.西安.哈尔滨等共10个城市同步开跑,并通过线上线下近十万人参与,共计累积了41.9722万公里的里程,超过了38.4万公里的地月距离,成功实现了"奔月计划". 文/张书乐 TMT行业观察者.游戏产业时评人,人民网.人民邮电报专栏作者 从多年深耕运动健康领域的经历来看,蒙牛成为"

[USACO Mar08] 牛跑步

http://www.cogs.pro/cogs/problem/problem.php?pid=133 ★★★   输入文件:cowjog.in   输出文件:cowjog.out   简单对比时间限制:1 s   内存限制:128 MB Bessie准备用从牛棚跑到池塘的方法来锻炼. 但是因为她懒,她只准备沿着下坡的路跑到池塘,然后走回牛棚. Bessie也不想跑得太远,所以她想走最短的路经. 农场上一共有M(1<=M<=10,000)条路,每条路连接两个用1..N(1<=N<

COGS 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是Bess

BZOJ 1598: [Usaco2008 Mar]牛跑步

A_star裸题 先反向建边跑一边spfa,然后把某点目前从起点跑的距离+它到终点的最短距离作为估价来跑A_star //Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector>