Ride to Office

GitHub跳转原题关系图返回列表

Charley 0 时刻从起点出发,途中遇到更快的人就跟上去;答案就是 t>=0 的同行人中 t + ceil(16200/v) 的最小值。

OJ: roj

题目 ID: 1227

难度:入门

标签:思维数学python

创建: 2026-09-30 00:42

更新: 2026-10-05 05:57

题目描述

起点到终点相距 4500 米。Charley 在时刻 0 从起点出发,必须与同行人同速骑行;遇到速度更快的人就跟上去。给出 n 个同行人的速度 v(km/h)与出发时间 t(t<0 表示提早出发),多组数据直到 n=0。求 Charley 到达终点的时间,结果向上取整。样例:第一组输入 4\n20 0\n25 -155\n27 190\n30 240 输出 780;第二组输入 2\n21 0\n22 34 输出 771。

思路

观察一:Charley 的到达时刻恰等于某个 t≥0 的同行人独自骑到的时刻,所以问题坍缩成"挑出最小 t+ceil(16200/v)";其中 16200=4500×3.6 是把 km/h 换算成 m/s 后的乘子。观察二:t<0 的同行人 Charley 出发时已在前方,永远追不上,直接跳过。

参考代码

Python 版:

python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-10-01 10:15
# update_at: 2026-10-01 10:15

import sys

METERS = 4500                        # 赛道长度(米)
DIST = METERS * 36 // 10              # 速度是 km/h,换算后 16200:除以 v 恰得骑行秒数


def solve() -> None:
    data = iter(map(int, sys.stdin.buffer.read().split()))
    out: list[str] = []

    while (n := next(data)) != 0:  # n = 0 表示输入结束
        arrivals = []  # Charley 可跟随(出发时刻不早于 0)的人的到达时刻
        for _ in range(n):
            v, t = next(data), next(data)  # 速度(km/h)、出发时刻(可为负)
            if t >= 0:
                arrivals.append(t + -(-DIST // v))  # ceil 除法:向上取整的骑行秒数

        out.append(str(min(arrivals, default=999999999)))  # 无人可跟时与参考实现一致

    print('\n'.join(out))


if __name__ == "__main__":
    solve()

C++ 版(同一算法):

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-10-05 05:57
 * update_at: 2026-10-05 05:57
 */
// main.cpp:Charley 必须与同行人同速跟随;挑出 t>=0 的人中最早到达终点的时刻。
#include <iostream>

typedef long long ll;

const ll DIST = 4500;                // 赛道长度(米)
const ll NUM = DIST * 36 / 10;        // 16200:4500m / (v km/h) 换算到秒数时除以 v 的值

int main() {
    ll n;
    std::cin >> n;
    while (n != 0) {                  // n = 0 表示输入结束
        ll best = (ll)9e18;            // 本组答案:所有可用同行人到达时刻的最小值
        for (ll i = 0; i < n; i++) {
            ll v, t;
            std::cin >> v >> t;
            if (t < 0) continue;       // 提前出发:Charley 出发时已在前方,追不上,跳过
            ll ride = (NUM + v - 1) / v; // 骑 4500m 需要 ceil(16200 / v) 秒
            ll arrive = t + ride;       // 该同行人独自到达终点的时刻
            if (arrive < best) best = arrive;
        }
        std::cout << best << '\n';
        std::cin >> n;
    }
    return 0;
}