Poj 2502 Subway(最短路)

题意:题意好理解,一个人步行的速度为每小时10公里,坐地铁的速度为40公里每小时。首先给出你两个点,分别是起点和终点。然后给出若干条铁路,每个铁路上至少有两个站点(也就是这条起点和终点),然后-1,-1为结束。问你从起点到终点最短需要多长时间。

题解:如何建图是一个问题。数据较小用临界矩阵来存图,我们可以把所有的站点,和起点终点当作图中的点来存图。存起来比较麻烦,需要存每个站点的时间,还有人到每个站点的时间。明白了要存什么,就看具体代码实现。spfa求最短路。

#include<cstring>
#include<cstdio>
#include<cmath>
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;

const int N = 30005;
const double INF = 1e9+0.0;

struct node{
	int x;
	int y;
}p[N];

int cnt,sum;
double dis[N];
int vis[N];
double ma[250][250];
double walk(node a,node b){
	return sqrt((double)(a.x-b.x) * (double)(a.x - b.x) + (double)(a.y - b.y) * (double)(a.y - b.y)) * 60.0 /10000.0;
}
double subway(node a,node b){
	return sqrt((double)(a.x-b.x) * (double)(a.x - b.x) + (double)(a.y - b.y) * (double)(a.y - b.y)) * 60.0 /40000.0;
}

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()){
		int u = q.front();
		q.pop();
		vis[u] = 0;
		for(int i = 1; i < cnt ; i++){
			if(dis[i] > dis[u] + ma[u][i]){
				dis[i] = dis[u] + ma[u][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] = walk(p[1],p[2]);   // 把起点当作第一个点 ,把终点当作第二个点 
	while(~scanf("%d%d",&p[cnt].x,&p[cnt].y)){  // 输入若干铁路。 
		if(p[cnt].x == -1 && p[cnt].y == -1){  // 结束标识 
			sum = 0 ;  // 当sum=0 表示现在输入一条全新的铁路。 
			continue;
		}
		for(int i = 1; i < cnt - sum ; i ++)  // 计算人到每个站点的时间 
			ma[i][cnt] = ma[cnt][i] = walk(p[cnt],p[i]);
		if(sum) // 若sum = 1 则,计算这条铁路到上个站点的时间。 若sum=0就不计算。很精髓 
			ma[cnt][cnt-1] = ma[cnt - 1][cnt] = subway(p[cnt],p[cnt-1]);
		cnt ++;
		sum = 1;
	}
//	for(int i = 1 ; i < cnt ; i++){
//		for(int j = 1; j < cnt ;j ++)
//			cout << ma[i][j] << " ";
//		cout << endl;
//	}
	spfa();
	printf("%d\n",(int)(dis[2] + 0.5));
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值