POJ2502 Subway【最短路+技巧】

Subway

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 14147 Accepted: 4584

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

Source

Waterloo local 2001.09.22

问题链接:POJ2502 Subway

问题描述:从家出发可以通过步行(10 km/h)和地铁(40 km/h)两种方式到学校,用二维坐标(x,y)描述家,学校,地铁站,描述地铁线的方式是通过顺序给出这条线上的地铁站位置,以(-1,-1)表示此次地铁线的结束,其中x和y的单位是m。同一条地铁线的相邻两个站是直线(双向),并且你到达地铁站后可以立即乘地铁,地铁站的总个数不超过200,问从家到学校的最短时间是多少分钟(四舍五入)

解题思路:将所有点都独立出来,包括家,学校和地铁站,由于点的总数不操作202,因此使用邻接矩阵表示图,需要解决的问题之一就是如何构建图g:g[i][j]表示结点i到结点j的时间(单位:h),非地铁站到其他点以及地铁站到非同一条线的地体站只能通过步行,因此只要用欧几里得距离除以10000m/h就能计算得出,对于同一条地铁线上的站,由于只有在相邻的站之间是直线,才能通过欧几里得距离处理40000m/h计算时间,不相邻的只能暂时通过步行方法计算得出时间,如何在程序中计算这些时间呢?这有一个小技巧,在点的结构体中有一个id属性,如果两个点的id值相差为1,那么它们就是同一条地铁线且相邻的站,否则就不是。程序学校编号为0,学校编号为1,构建好图后,就使用最短路算法计算最短路即可,程序使用spfa算法,最后的到的结果是小时,化成分钟后四舍五入即可:int(dist[1]*60+0.5)

AC的C++代码:

#include<iostream>
#include<cmath>
#include<cstring>
#include<queue>

using namespace std;

const int N=300;
const double INF=9000000.0;
const double SP1=40000.0;
const double SP2=10000.0;

double g[N][N];
struct Node{
	double x,y;
	int id;
}p[N];

//返回结点个数 
int read()
{
	double x,y;
	int k=0,id=3;
	while(~scanf("%lf%lf",&x,&y)){
		id++;
		if(x==-1&&y==-1) continue;
		p[k].x=x,p[k].y=y,p[k].id=id;
		k++;
	}
	p[0].id=0,p[1].id=2;
	for(int i=0;i<k;i++)
	  for(int j=i;j<k;j++)
	    if(i==j)
	      g[i][j]=0;
	    else if(p[i].id-p[j].id==-1)//如果在同一条地铁线上 
	      g[i][j]=g[j][i]=sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y))/SP1;
	    else
		  g[i][j]=g[j][i]=sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y))/SP2; 
	return k;
}
//起点编号为0 终点编号为1 求起点到终点的最短路径
double dist[N];
bool vis[N];
int cnt[N];

bool spfa(int n,int s)//结点数和起点 
{
	memset(dist,INF,sizeof(dist));
	memset(vis,false,sizeof(vis));
	memset(cnt,0,sizeof(cnt));
	cnt[s]=1;
	vis[s]=true;
	dist[s]=0;
	queue<int>q;
	q.push(s);
	while(!q.empty()){
		int f=q.front();
		q.pop();
		vis[f]=false;
		for(int i=0;i<n;i++)
		  if(dist[i]>dist[f]+g[f][i]){
		  	dist[i]=dist[f]+g[f][i];
		  	if(!vis[i]){
		  		q.push(i);
		  		cnt[i]++;
		  		vis[i]=true;
		  		if(cnt[i]>n)
		  		  return false;
			  }
		  }
	}
	return true;
}


int main()
{
	int n=read();
	if(spfa(n,0))
	  printf("%d\n",int(dist[1]*60+0.5));
	return 0;
} 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值