题目出处:《信息学奥赛一本通 (C++)版》P467页
线上OJ: 信息学奥赛一本通(C++版)在线评测系统
核心思想:
- 把街道看到边 e,街道的两端看成顶点 v
- 每条马路都是双向 + 每个方向都有一根车道且都要扫雪 → 有向边
- 从起点出发,扫完每一根车道,最终回到起点 → 一定存在欧拉回路
- 通过画图分析可知,最短路径是每个街道都正反各走一次(即每条有向边仅走除雪的一次,不走空车)
- 所以,本题实际上只要求出街道的长度,除以铲雪时的速度即可
- 由于每个街道要正反各走一次,所以长度要*2
注意1:由于涉及到距离公式 ,本题应用 long long
注意2:题目中的“且都是双向一个车道”有歧义,原本以为是只有一根车道,又能正向走又能反向走。但根据题目样例输出的 3:55 推出,实际上是双向各有一根车道。
题中的样例输出 3:55 推导如下图:
题解代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
/*
核心思想:
1. 把街道看到边e,街道的两端看成顶点v
2. 每条马路都是双向 + 每个方向都有一根车道且都要扫雪 →有向边
3. 从起点出发,扫完每一根车道,最终回到起点 →一定存在欧拉回路
4. 通过画图分析可知,最短路径是每个街道都正反各走一次(即每条有向边仅走除雪的一次,不走空车)
5. 所以,本题实际上只要求出街道的长度,除以铲雪时的速度即可
6. 由于每个街道要正反各走一次,所以长度要*2
注意:由于涉及到距离公式 d = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)),本题应用 long long
*/
int main()
{
ll a0, y0, x1, y1, x2, y2;
cin >> a0 >> y0; // 读入初始坐标。由于题中已保证从起点一定可以到达任何街道,所以这组坐标其实没用
// 每读入街道的两个顶点,就计算这个街道的长度,并*2倍
double d;
while(cin >> x1 >> y1 >> x2 >> y2)
d += 2*sqrt(pow((x1 - x2), 2) + pow((y1 - y2), 2));
ll h, m;
h = d/20000; // t:时间 = 距离 / 速度 , 自动取整就是 h
m = round((double(d/20000) - h) * 60); // 计算分钟数。举例:(3.914-3)*60=54.84分钟,四舍五入为55
// 如果四舍五入后,分钟数m变为60,则手动更新h和m
if(m == 60)
{
h++;
m = 0;
}
printf("%lld:%02lld\n", h, m);
return 0;
}