欧拉回路 - 铲雪车 - AcWing 1123

欧拉回路 - 铲雪车 - AcWing 1123

随着白天越来越短夜晚越来越长,我们不得不考虑铲雪问题了。

整个城市所有的道路都是双向车道,道路的两个方向均需要铲雪。因为城市预算的削减,整个城市只有 1 辆铲雪车。

铲雪车只能把它开过的地方(车道)的雪铲干净,无论哪儿有雪,铲雪车都得从停放的地方出发,游历整个城市的街道。

现在的问题是:最少要花多少时间去铲掉所有道路上的雪呢?

输入格式

输入数据的第 1 行表示铲雪车的停放坐标 (x,y),x,y 为整数,单位为米。

下面最多有4000行,每行给出了一条街道的起点坐标和终点坐标,坐标均为整数,所有街道都是笔直的,且都是双向车道。

铲雪车可以在任意交叉口、或任何街道的末尾任意转向,包括转 U 型弯。

铲雪车铲雪时前进速度为 20 千米/时,不铲雪时前进速度为 50 千米/时。

保证: 铲雪车从起点一定可以到达任何街道。

输出格式

输出铲掉所有街道上的雪并且返回出发点的最短时间,精确到分钟,四舍五入到整数。

输出格式为”hours:minutes”,minutes不足两位数时需要补前导零。
具体格式参照样例。

数据范围

− 1 0 6 ≤ x , y ≤ 1 0 6 −10^6≤x,y≤10^6 106x,y106

所有位置坐标绝对值不超过 106

输入样例:

0 0
0 0 10000 10000
5000 -10000 5000 10000
5000 10000 10000 10000

输出样例:

3:55

样例解释

输出结果表示共需3小时55分钟。


分析:

由 题 意 , 给 定 一 个 图 , 由题意,给定一个图,

要 经 过 图 中 每 条 边 至 少 两 次 , 求 遍 历 这 个 图 的 最 短 时 间 是 多 少 , 要经过图中每条边至少两次,求遍历这个图的最短时间是多少,

由 于 车 速 固 定 , 等 价 于 计 算 出 遍 历 这 个 图 的 路 程 和 的 最 小 值 是 多 少 。 由于车速固定,等价于计算出遍历这个图的路程和的最小值是多少。

尽 管 不 铲 雪 的 速 度 是 50 k m / h , 但 是 若 走 过 多 余 的 路 程 , 仍 然 不 是 最 短 路 程 。 尽管不铲雪的速度是50km/h,但是若走过多余的路程,仍然不是最短路程。 50km/h

因 此 , 我 们 要 确 保 经 过 边 的 数 量 尽 量 少 。 因此,我们要确保经过边的数量尽量少。

但是本题应当看作是有向图,而非无向图。

原因:

本 题 要 求 每 条 边 一 来 一 回 经 过 两 次 , 本题要求每条边一来一回经过两次,

若 看 作 有 向 图 , 由 于 每 条 边 都 会 对 边 的 两 个 端 点 贡 献 1 个 出 度 和 1 个 入 度 , 若看作有向图,由于每条边都会对边的两个端点贡献1个出度和1个入度, 11

这 就 保 证 了 每 个 点 的 出 度 和 入 度 相 等 , 从 而 确 定 图 中 存 在 欧 拉 回 路 。 这就保证了每个点的出度和入度相等,从而确定图中存在欧拉回路。

若 看 作 是 无 向 图 , 相 当 于 同 一 条 边 经 过 两 次 。 则 不 能 确 定 是 否 存 在 欧 拉 回 路 。 若看作是无向图,相当于同一条边经过两次。则不能确定是否存在欧拉回路。

故 本 题 的 最 优 解 , 应 当 是 欧 拉 回 路 正 向 和 反 向 各 跑 一 遍 。 故本题的最优解,应当是欧拉回路正向和反向各跑一遍。

我 们 仅 需 将 所 有 边 权 累 加 起 来 即 可 得 出 最 短 路 程 。 我们仅需将所有边权累加起来即可得出最短路程。

注意:

计 算 距 离 的 时 候 , 考 虑 到 一 些 精 度 问 题 , 将 点 坐 标 类 型 设 置 成 d o u b l e 。 计算距离的时候,考虑到一些精度问题,将点坐标类型设置成double。 double

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>

using namespace std;

double get_dis(double a1,double b1,double a2,double b2)
{
    double dx=a1-a2, dy=b1-b2;
    return sqrt(dx*dx+dy*dy);
}

int main()
{
    double a1,b1,a2,b2;
    cin>>a1>>b1;
    
    double sum=0;
    while(cin>>a1>>b1>>a2>>b2) sum+=get_dis(a1,b1,a2,b2);
    
    sum=sum/1000*2;
    int minute=round(sum/20*60);
    int hour=minute/60;
    minute%=60;
    
    printf("%d:%02d\n",hour,minute);
    
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值