《信息学奥赛一本通 (C++)版》铲雪车(snow)

159 阅读2分钟

题目出处:《信息学奥赛一本通 (C++)版》P467页

线上OJ: 信息学奥赛一本通(C++版)在线评测系统

核心思想

  1. 把街道看到边 e,街道的两端看成顶点 v
  2. 每条马路都是双向 + 每个方向都有一根车道且都要扫雪 → 有向边
  3. 从起点出发,扫完每一根车道,最终回到起点 → 一定存在欧拉回路
  4. 通过画图分析可知,最短路径是每个街道都正反各走一次(即每条有向边仅走除雪的一次,不走空车)
  5. 所以,本题实际上只要求出街道的长度,除以铲雪时的速度即可
  6. 由于每个街道要正反各走一次,所以长度要*2

注意1:由于涉及到距离公式 d=(x1x2)2+(y1y2)2))d=\sqrt{(x_{1}-x_{2})^{2}+(y_{1}-y_{2})^{2}))},本题应用 long long

注意2:题目中的“且都是双向一个车道”有歧义,原本以为是只有一根车道,又能正向走又能反向走。但根据题目样例输出的 3:55 推出,实际上是双向各有一根车道。

image.png

题解代码

#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;
}