题目概述
城市地图是一个二维坐标系,你要从家里到学校,行走速度10km/h,城市中有地铁线路,地铁只在行驶在某些点之间,两点之间的行驶路线都是直线,地铁速度40km/h,给定家,学校,地铁站点的位置以及地铁线路,问最快多久到学校
每次到地铁站时都会立刻坐上地铁,并且可以在线路上的任何站点下车
地图坐标的单位是米
时限
1000ms/3000ms
输入
第一行两对整数,分别描述家和学校的位置,其后若干行,每行若干对整数,描述一条地铁线上相邻站点的位置,每行以-1 -1结束,输入到EOF结束,数据只有一组
限制
城市中最多200个地铁站
输出
一个数,到学校最少需要的分钟数,四舍五入到整数
样例输入
0 0 10000 1000
0 200 5000 200 7000 200 -1 -1
2000 600 5000 600 10000 600 -1 -1
样例输出
21
讨论
图论,单源最短路,bellman_ford队列优化算法,首先一眼能看出是单元最短路,但是这个题麻烦在构图,走路可以在任何两点间穿梭,而地铁只能在相邻两点之间跑,需要注意,可能会出现V形地铁线,使得两点之间坐地铁比走路还慢,因而地铁线上非相邻两点间也要算行走用时
实现层面上,首先注意,题目给的速度是km/h,而地图单位是m,而且最后输出的是min,这中间牵扯的简单换算都不能忽略,构图时,这显然是得用邻接矩阵,先构造每条地铁线相邻两点之间的用时,之后构造行走部分的用时,遇到有地铁两点需要在行走和地铁之间取较小值,不能直接取地铁的用时,最后一遍最短路,返回结果即可
题解状态
532K,16MS,C++,1546B
题解代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 204
#define memset0(a) memset(a,0,sizeof(a))
int x[MAXN], y[MAXN];//地图上点的坐标
double graph[MAXN][MAXN], dist[MAXN];//邻接矩阵 最短路长度
queue<int>q;//辅助队列
bool inq[MAXN];//辅助数组 在队列中
double dis(int x1, int y1, int x2, int y2)//两点间距离 这回要用好几次 就没删
{
return sqrt(double(x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2));//传的参数是int 需要强转一下 否则sqrt是c++11的int型 poj不认
}
double fun()
{
scanf("%d%d%d%d", &x[0], &y[0], &x[1], &y[1]);//intput//家和学校分别是0点和1点
int index = 2;
while (~scanf("%d%d", &x[index], &y[index])) {//input//这部分是读取地铁线的情况以及处理
index++;
while (scanf("%d%d", &x[index], &y[index]) && (x[index] != -1 || y[index] != -1)) {
graph[index - 1][index] = graph[index][index - 1] = dis(x[index], y[index], x[index - 1], y[index - 1]) / 40000;//由于单位换算 40*1000
index++;
}
}
for (int p = 0; p < index; p++) {//下面处理行走部分的用时 这种写法完全可以整合成一个for
for (int i = 0; i < p; i++) {
graph[p][i] = graph[i][p];
}
for (int i = p + 1; i < index; i++) {
if (!graph[p][i])
graph[p][i] = dis(x[p], y[p], x[i], y[i]) / 10000;
else
graph[p][i] = min(graph[p][i], dis(x[p], y[p], x[i], y[i]));
}
}
for (int p = 1; p < index; p++)//下面是bellman_ford算法
dist[p] = INF;
q.push(0);
inq[0] = 1;
while (!q.empty()) {
int a = q.front();
q.pop();
inq[a] = 0;
for (int p = 0; p < index; p++) {
if (a != p&&dist[p] > dist[a] + graph[a][p]) {
dist[p] = dist[a] + graph[a][p];
if (!inq[p]) {
q.push(p);
inq[p] = 1;
}
}
}
}
return dist[1] * 60;//从小时换算到分钟
}
int main(void)
{
//freopen("vs_cin.txt", "r", stdin);
//freopen("vs_cout.txt", "w", stdout);
printf("%.0lf\n", fun());//output
}
EOF