POJ2502 subway(dijkstra以最短时间代替最短路)

L – Subway
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu
Submit 
Status 
Practice 
POJ 2502

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通过是无压力的。

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/llzhh/article/details/52421527
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞