1. 程式人生 > >最短路練習12/poj/2502 Subway dijkstar,spfa,floyd都可以解決

最短路練習12/poj/2502 Subway dijkstar,spfa,floyd都可以解決

Subway
Time Limit: 1000MSMemory Limit: 65536K
Total Submissions: 9766Accepted: 3163

Description

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
這道題做的時間不短,花了將近4小時,自己的程式碼錯誤一直沒找出來。看了題解也找了2小時才找出錯誤。

發現自己思考問題不全面,並且一旦入坑就很難跳出。(無法擺脫自己的定向思維)(這是個大問題)

題意:現在學生要去學校,學生和學校的座標第一行給出,接下來每一行都代表一條地鐵的軌道,直到-1,-1表明這條地鐵結束,地鐵站的每個座標已給出。求小明到達學校的最短時間。

思路難點:建圖非常困難,靠考慮很多細節,比如:地鐵的第一站,要與前面出現的所有點都要求出距離(求出步行時間)。地鐵的其他站(二站,三站,四站等等),與他的前一站求出(火車行走時間),並且與(除了他的前一站外的)所有座標求出步行時間,地鐵(不相鄰的站)的路線並不一定是直的。

因為有可能出現這種情況站1到站3的步行時間可能要比乘地鐵時間更短。所以只有相鄰的兩站我們才用地鐵速度,其他都用步行速度。

還有一個挺坑的地方,樣例都不能讓咱們輕鬆輸出。你必須把多組輸入改一下才可以,改成k=8,while(k--){  };這樣就能試樣例了,提交前不要忘了該成多組輸入哦。

dijkstar,spfa 是我自己寫的程式碼,比較低調。最後的floyd是搜的部落格,比較高大上。

試了各種方法做這道題。dijkstar  AC程式碼:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
#include<string>
#define LL long long
#define eps 1e-8
#define N 3005
#define M 100005
using namespace std;
const int mod = 1e7+7;
const double inf = 1000000000.0;
const int maxx = 1e6 +10;
struct node
{
    int x,y;
} p[N];
int cnt,sum,f;
double dis[N],fx;
int vis[N];
double ma[N][N];
void dijkstra()
{
    for(int i=0;i<cnt;i++)
        dis[i]=ma[1][i];
     memset(vis,0,sizeof(vis));
     vis[1]=1;
     dis[1]=0;
     double sum;
     int point;
     for(int i=1;i<cnt;i++)
     {
         sum=inf;
         point =-1;
         for(int j=1;j<cnt;j++)
         {
             if(!vis[j]&&dis[j]<sum)
             {
                 sum=dis[j];
                 point =j;
             }
         }
         if(point!=-1)
         {
             vis[point]=1;
             for(int j=1;j<cnt;j++)
             {
                 if(dis[point]+ma[point][j]<dis[j])
                 {
                     dis[j]=dis[point ]+ma[point ][j];
                 }
             }
         }
     }
}
int main()
{
    cnt=3;
    sum=0;
    for(int i=0; i<240; i++)
        for(int j=0; j<240; j++)
            ma[i][j]=i==j?0.0:inf;
    scanf("%d%d%d%d",&p[1].x,&p[1].y,&p[2].x,&p[2].y);
    ma[2][1]=ma[1][2]=sqrt((double)(p[1].x-p[2].x)*(double)(p[1].x-p[2].x)+(double)(p[1].y-p[2].y)*(double)(p[1].y-p[2].y))*60.0/10000.0;
    while(~scanf("%d%d",&p[cnt].x,&p[cnt].y))
    {
        if(p[cnt].x==-1&&p[cnt].y==-1)
        {
            sum=0;
            continue;
        }
        for(int i=1; i<cnt-sum; i++)//注意這裡的sum的值用的非常巧妙,注意體會sum==0或1的用意
            ma[i][cnt]=ma[cnt][i]=sqrt((double)(p[cnt].x-p[i].x)*(double)(p[cnt].x-p[i].x)+(double)(p[cnt].y-p[i].y)*(double)(p[cnt].y-p[i].y))*3.0/500.0;
        if(sum)
            ma[cnt][cnt-1]=ma[cnt-1][cnt]=sqrt((double)(p[cnt].x-p[cnt-1].x)*(double)(p[cnt].x-p[cnt-1].x)+(double)(p[cnt].y-p[cnt-1].y)*(double)(p[cnt].y-p[cnt-1].y))*3.0/2000.0;
        cnt++;sum=1;
    }
    dijkstra();
    printf("%.0f\n",dis[2]);
}
spfa  AC程式碼:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
#include<string>
#define LL long long
#define eps 1e-8
#define N 30005
#define M 100005
using namespace std;
const int mod = 1e7+7;
const double inf = 1000000000.0;
const int maxx = 1e6 +10;
struct node {int x,y;}p[N];
int cnt,sum,f;
double dis[N];
int vis[N];
double ma[250][205];
void spfa()
{
    memset(vis,0,sizeof(vis));
    for(int i=0;i<240;i++)
        dis[i]=inf;
    queue<int>q;
    dis[1]=0;
    vis[1]=1;
    q.push(1);
    while(!q.empty())
    {
        f=q.front();
        q.pop();
        vis[f]=0;
        for(int i=1;i<cnt;i++)
        {
            if(dis[i]>dis[f]+ma[f][i])
            {
                dis[i]=dis[f]+ma[f][i];
                if(!vis[i])
                {
                    vis[i]=1;
                    q.push(i);
                }
            }
        }
    }
}
int main()
{
    cnt=3;sum=0;
    for(int i=0;i<240;i++)
      for(int j=0;j<240;j++)
        ma[i][j]=i==j?0.0:inf;
    scanf("%d%d%d%d",&p[1].x,&p[1].y,&p[2].x,&p[2].y);
    ma[2][1]=ma[1][2]=sqrt((double)(p[1].x-p[2].x)*(double)(p[1].x-p[2].x)+(double)(p[1].y-p[2].y)*(double)(p[1].y-p[2].y))*60.0/10000.0;
    while(~scanf("%d%d",&p[cnt].x,&p[cnt].y))
    {
        if(p[cnt].x==-1&&p[cnt].y==-1)
        {
            sum=0;
            continue;
        }
        for(int i=1;i<cnt-sum;i++)
            ma[i][cnt]=ma[cnt][i]=sqrt((double)(p[cnt].x-p[i].x)*(double)(p[cnt].x-p[i].x)+(double)(p[cnt].y-p[i].y)*(double)(p[cnt].y-p[i].y))*60.0/10000.0;
           if(sum) 
            ma[cnt-1][cnt]=ma[cnt][cnt-1]=sqrt((double)(p[cnt].x-p[cnt-1].x)*(double)(p[cnt].x-p[cnt-1].x)+(double)(p[cnt].y-p[cnt-1].y)*(double)(p[cnt].y-p[cnt-1].y))*60.0/40000.0;
        cnt++;sum=1;
    }
    spfa();
    printf("%d\n",(int)(dis[2]+0.5));
}
flody  AC程式碼:
#include <iostream>  
#include <cstring>  
#include <deque>  
#include <cmath>  
#include <queue>  
#include <stack>  
#include <list>  
#include <map>  
#include <set>  
#include <string>  
#include <vector>  
#include <cstdio>  
#include <bitset>  
#include <algorithm>  
using namespace std;  
#define Debug(x) cout << #x << " " << x <<endl  
#define Memset(x, a) memset(x, a, sizeof(x))  
const int INF = 0x3f3f3f3f;  
typedef long long LL;  
typedef pair<int, int> P;  
#define FOR(i, a, b) for(int i = a;i < b; i++)  
#define MAX_N 2520  
int n;  
double G[MAX_N][MAX_N];  
struct Point{  
    int x;  
    int y;  
}p[MAX_N];  
double walk(int i, int j){  
    double l = sqrt((double)(p[i].x - p[j].x) * (p[i].x - p[j].x) + (double)(p[i].y - p[j].y) * (p[i].y - p[j].y));  
    return  l * 60 / 10000.0;  
}  
double subway(int i, int j){  
    double l = sqrt((double)(p[i].x - p[j].x) * (p[i].x - p[j].x) + (double)(p[i].y - p[j].y) * (p[i].y - p[j].y));  
    return l * 60.0 / 40000.0;  
}  
void solve(){  
    for(int k = 1; k <= n; k++){  
        for(int i = 1;i <= n; i++){  
            for(int j = 1;j <= n; j++){  
                G[i][j] = min(G[i][j], G[i][k] + G[k][j]);  
            }  
        }  
    }  
}     
int main(){  
    //freopen("in.cpp", "r", stdin);  
    scanf("%d%d%d%d", &p[1].x, &p[1].y, &p[2].x, &p[2].y);  
    G[1][2] = G[2][1] = walk(1, 2);  
    int j = 0;n = 3;  
    int a, b;  
    while(scanf("%d%d",&a,&b) != EOF){    
        if(a == -1 && b == -1)     
            j = 0;    
        else{     
            p[n].x = a, p[n].y = b;    
            for(int i = 1;i < n - j; i++){     
                G[i][n] = G[n][i] = walk(i,n);    
            }     
            for(int i = n-j; i < n; i++){    
                G[i][n] = G[n][i] = subway(i,n);    
            }    
            j = 1, n++;     
        }     
    }      
    n--;  
    solve();  
    printf("%.0f\n", G[1][2]);  
    return 0;  
}