1. 程式人生 > >Subway (最短路問題)

Subway (最短路問題)

題目: You have just moved from a quiet Waterloo neighbourhood to a big, noisy city. Instead of getting to ride your bike to school every day, you now get to walk and take the subway. Because you don't want to be late for class, you want to know how long it will take you to get to school.
You walk at a speed of 10 km/h. The subway travels at 40 km/h. Assume that you are lucky, and whenever you arrive at a subway station, a train is there that you can board immediately. You may get on and off the subway any number of times, and you may switch between different subway lines if you wish. All subway lines go in both directions. Input Input consists of the x,y coordinates of your home and your school, followed by specifications of several subway lines. Each subway line consists of the non-negative integer x,y coordinates of each stop on the line, in order. You may assume the subway runs in a straight line between adjacent stops, and the coordinates represent an integral number of metres. Each line has at least two stops. The end of each subway line is followed by the dummy coordinate pair -1,-1. In total there are at most 200 subway stops in the city. Output Output is the number of minutes it will take you to get to school, rounded to the nearest minute, taking the fastest route. Sample Input
0 0 10000 1000
0 200 5000 200 7000 200 -1 -1 
2000 600 5000 600 10000 600 -1 -1
Sample Output
21

題目大意:

先輸入兩個點的座標是self and School的座標

然後輸入一系列的座標,其中以-1 -1結尾的表示之前的座標是在一個地鐵線上,地鐵的執行速度是40km/h.

坑點:

1.輸入資料是距離單位是m,讓你求的時間的單位是分鐘。而題中的速度是km/h,所以需要轉化一下

2.在同一地鐵線上,兩個地鐵站不能直接建造“地鐵線路”,因為這兩點的地鐵線路可能是折線(到另一個地鐵站必須按照地鐵的線路去),當然兩個地鐵站之間可以選擇步行到達。

3.最扯淡的也就是資料的輸入方式。看完輸入就搜部落格去了,,ԾㅂԾ,,

題解:

將所有座標都編上號1~n 其在同一條線路上的地鐵都將座標用一個相同的特徵元素標記(那麼不同地鐵線上的特種元素標記的值肯定不同),然後求任意兩個點座標直接通過所用的時間,最後用dijkstra求1->2的最短時間即可(資料要四捨五入)。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<math.h>
#define N 250
#define INF 0x7fffffff
using namespace std;
const double vb=10.0*1000/60.0;//Step   速度  m/分鐘
const double vs=40.0*1000/60.0;//Subway 速度  m/分鐘
double map[N][N],dis[N];//從i到j所用的時間
int book[N];
struct node {
    int  x,y,k;//K為特徵元素
}point[N]; //把位置看成點 //結構體下標就是點的編號
double _distant(double x1,double y1,double x2,double y2)
{
    x1=x1-x2;
    y1=y1-y2;
    return sqrt(x1*x1+y1*y1);
}
void dijkstra(int n)
{
    int t=n-1,u;
    double mid,minn;
    while(t--)
    {
        minn=INF;
        for(int i=1;i<=n;i++)
        {
            if((!book[i])&&dis[i]<minn)
            {
                minn=dis[i];
                u=i;
            }
        }
        book[u]=1;
        if(u==2)
            return ;
        for(int i=1;i<=n;i++)
        {
            mid=dis[u]+map[u][i];
            if(mid<dis[i])
                dis[i]=mid;
        }
    }
}
int main()
{
    int cnt=1,k=1;//k表示不同的種類數//同一種類的是在同一線路上
    double mid;
    scanf("%d %d",&point[cnt].x,&point[cnt].y);
    point[cnt++].k=k++;
    scanf("%d %d",&point[cnt].x,&point[cnt].y);
    point[cnt++].k=k++;
    while(~scanf("%d %d",&point[cnt].x,&point[cnt].y))//   cnt=3   k=3
    {
        point[cnt++].k=k;
        while((scanf("%d %d",&point[cnt].x,&point[cnt].y))&&point[cnt].x!=-1)
            point[cnt++].k=k;
        k++;
//        if(k==5)
//            break;
    }//共cnt-1個點  其k相同的就是在同一線路上的 從一開始編號的
    cnt--;
//    printf("cnt=%d\n",cnt);
    for(int i=1;i<=cnt;i++)
        for(int j=1;j<=cnt;j++)
            map[i][j]=INF;
    for(int i=1;i<=cnt;i++)
            map[i][i]=0;
    for(int i=1;i<=cnt;i++)
    {
        for(int j=i+1;j<=cnt;j++)//求編號為i的到編號為J的時間
        {
            mid=_distant(point[i].x,point[i].y,point[j].x,point[j].y);
            if(point[i].k==point[j].k&&(j==i+1))//一條地鐵線上且相鄰的點
                mid=mid/vs;
            else
                mid=mid/vb;
            if(mid<map[i][j])
                map[i][j]=map[j][i]=mid;
        }
    }
//用於測試資料檢視map內資料
/*
    for(int i=0;i<=cnt;i++)
        printf("%5d  ",i);
    printf("\n");
    for(int i=1;i<=cnt;i++)
    {
        printf("%5d  ",i);
        for(int j=1;j<=cnt;j++)
        {
            printf("%5.1lf  ",map[i][j]);
        }
         printf("\n");
    }
*/
     for(int i=1;i<=cnt;i++)//記錄1到其他點的時間
        dis[i]=map[1][i];
      book[1]=1;
      dijkstra(cnt);
//      for(int i=1;i<=cnt;i++)
//          printf("dis[%d]=%.2lf\n",i,dis[i]);
      printf("%.0lf\n",dis[2]);
}
參考部落格:https://www.cnblogs.com/Sunshine-tcf/p/5752027.html