1. 程式人生 > >POJ2502 subway(dijkstra以最短時間代替最短路)

POJ2502 subway(dijkstra以最短時間代替最短路)

L - Subway Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu

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

題目簡潔明瞭,但是一開始我寫的時候把10km/h化成了1000m/h,死活算不出來,後面才發現原來是10000km/h,真是智障啊!總而言之,人的速度是10km/h,地鐵是40km/h,化出來就500/3 m/min,2000/3 m/min,這道題的最短走法是歐幾里得距離,我一開始還以為只能走曼哈頓距離。

解法其實,看起來挺簡單的,但是我真的想了兩天才想通,中間別人還給了我提示。要我現在總結的話,就是:開個臨接矩陣,把家的座標當成ID 0,地鐵站就依次是2,3,4.。。。然後最後一個就是學校的ID,然後用n²的時間複雜度把每個點之間的距離算出來,也就得到了時間,把時間放進臨接矩陣中,然後dijkstra跑一次就出來了。

其實問題就是,地鐵線路和人的走路如何區分,畢竟一個快一個慢。所以,我們在讀入地鐵的時候就要開始建圖了,地鐵啊,只能相鄰兩個站之間走,只需要把他們兩個站之間通過需要的時間放進鄰接矩陣中,其它站都不需要管。這裡我們處理了一次。後面,再對所有點之間計算時間,此時使用速度是步行速度,就是兩個for,這裡面加個min判斷,只取小的,這樣步行花費時間就不會代替地鐵兩個站點相連時候第一次得到的時間了,因為步行花費時間肯定比較大。這樣鄰接矩陣就建完了。

程式碼如下:

#include<stdio.h>
#include<string.h>
#include<math.h>
#define MAX 0x3f3f3f3f
#define min(a,b) a>b?b:a 
double G[311][311];
int subx[311],suby[311],stop_number,hx,hy,sx,sy;
double time[311];
void dijkstra()
{
	int mark[311] = {0};
	int i,j,pos;
	double min;
	for(i = 1; i <= stop_number; i++)
	{
		time[i] = G[0][i];
	} 

	mark[0] = 1;
	
	for(i = 1; i <= stop_number + 1; i++)
	{
		min = MAX;
		for(j = 1; j <= stop_number; j++)
		{
			if(!mark[j] && time[j] < min)
			{
				pos = j;
				min = time[j];
			}
		}
		
		mark[pos] = 1;
		
		if(min == MAX)
			break;
		
		for(j = 1; j <= stop_number; j++)
		{
			if(!mark[j] && time[j] > time[pos] + G[pos][j])
			{
				time[j] = time[pos] + G[pos][j];
			}
		}
	}
}

int main()
{
	int k = 1, i, x, y, j;
	double len;
	memset(subx,-1,sizeof(subx));
	memset(suby,-1,sizeof(suby));
	for(i=0;i<311;i++)
		for(j=0;j<311;j++)
			G[i][j]=MAX;
	scanf("%d%d%d%d", &hx, &hy, &sx, &sy); 
	i = 1;
	while(scanf("%d%d",&x,&y)!=EOF)//讀入地鐵 
	{
		subx[i] = x;
		suby[i++] = y;
		while(scanf("%d%d",&x,&y) == 2)
		{
			if(x == -1 && y == -1)
				break;			
			len = sqrt( (x - subx[i - 1]) * (x - subx[i - 1]) + (y - suby[i - 1]) * (y - suby[i - 1]) );
			G[i - 1][i] = G[i][i - 1] = min(G[i - 1][i], len * 3.0 / 2000.0);
			
			subx[i] = x;
			suby[i] = y;
			i++;
		}
	}
	stop_number = i;
	for(i = 1; i < stop_number - 1; i++)//地鐵線路數目
	{
		for(j = 1; j < stop_number; j++)//某條線路的某個站點 
		{
			len = sqrt( (subx[i] - subx[j]) * (subx[i] - subx[j]) + (suby[i] - suby[j]) * (suby[i] - suby[j]) );
			G[i][j] = G[j][i] = min(G[i][j], len * 3.0 / 500.0);
		}
	} 
	for(i = 1;i < stop_number; i++)
	{
		G[0][i] = G[i][0] = sqrt( (hx - subx[i]) * (hx - subx[i]) + (hy - suby[i]) * (hy - suby[i]) ) * 3.0 / 500.0;
	}
	for(i = 1;i < stop_number; i++)
	{
		G[stop_number][i] = G[i][stop_number] = sqrt( (sx - subx[i]) * (sx - subx[i]) + (sy - suby[i]) * (sy - suby[i]) ) * 3.0 / 500.0;
	}
	G[0][stop_number] = G[stop_number][0] = sqrt( (hx - sx) * (hx - sx) + (hy - sy) * (hy - sy) ) * 3.0 / 500.0;
	dijkstra(); 
	printf("%d\n",(int)(time[stop_number] + 0.5) );
}

因為資料量很小,最多才200個站點,又是隻跑一次的,所以0ms通過是無壓力的。