救援

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

每个屋顶独立往返一次,累加航行时间与上下船时间,最后向上取整。

OJ: roj

题目 ID: 1073

难度:入门

标签:数学模拟

创建: 2026-01-12 11:20

更新: 2026-10-05 00:11

题目描述

救生船从原点(大本营)出发,营救若干屋顶上的人回到大本营。屋顶数 n 及每个屋顶的坐标 (x, y)、人数 c 由输入给出。船每次从原点出发,速度 50 米/分钟;到达屋顶救下所有人,每人上船 1 分钟,船原路返回,每人下船 0.5 分钟。假设原点与任意屋顶的连线不穿过其它屋顶。求完成所有救援并返回大本营的总时间,向上取整到分钟。

输入:第一行一个整数 n;接下来 n 行,每行两个实数 x、y 和一个整数 c。输出:救援总时间(向上取整到分钟)。

样例输入:1\n30 40 3;样例输出:7。

思路

每个屋顶必须独立往返一次,对第 i 个屋顶贡献 2⋅xi2+yi250+1.5ci2\cdot\frac{\sqrt{x_i^2+y_i^2}}{50}+1.5c_i 分钟,把所有屋顶累加后向上取整即可。

参考代码

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-01-12 11:20
# update_at: 2026-01-12 11:20

import math
import sys
from collections.abc import Iterator


def read_triples(data: Iterator[str]) -> Iterator[tuple[float, float, int]]:
    """依次读出每个屋顶的横坐标、纵坐标、人数。"""
    while True:
        try:
            x, y, c = next(data), next(data), next(data)
            yield float(x), float(y), int(c)
        except StopIteration:
            return


def rescue_time(x: float, y: float, c: int) -> float:
    """单次往返救援一个屋顶的耗时:往返航行 + 上下船。"""
    dist = math.hypot(x, y)          # 大本营到屋顶的欧氏距离
    sail = dist / 50.0               # 单程航行时间(分钟)
    return 2.0 * sail + 1.5 * c      # 往返 + 每人上船 1 分钟、下船 0.5 分钟


def solve() -> None:
    data = iter(sys.stdin.buffer.read().split())
    n = int(next(data))              # 屋顶数,仅用于完整性检查
    total = sum(rescue_time(x, y, c) for x, y, c in read_triples(data))
    print(math.ceil(total))


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 00:11
 * update_at: 2026-10-05 00:11
 */

// main.cpp:每个屋顶独立往返一次,累加航行时间与上下船时间,最后向上取整。
// 总时间 = Σ (2 * 距离 / 50 + 1.5 * 人数),距离 = sqrt(x^2 + y^2)。

#include <cmath>
#include <cstdio>

typedef long long ll;

int main() {
    int n;
    scanf("%d", &n);
    double total = 0.0; // 累计所有屋顶救援总时间(分钟,含小数)
    for (int i = 0; i < n; ++i) {
        double x, y;
        int c; // 该屋顶人数
        scanf("%lf %lf %d", &x, &y, &c);
        double dist = std::sqrt(x * x + y * y); // 大本营到屋顶的欧氏距离(米)
        double sail = dist / 50.0;              // 单程航行时间(分钟),速度 50 米/分钟
        total += 2.0 * sail + 1.5 * c;          // 往返航行 + 上船 1 分钟/人 + 下船 0.5 分钟/人
    }
    // 向上取整:用 ceil 处理一般情况;当 total 几乎正整数时 ceil 仍给出正确整数值
    ll ans = (ll)std::ceil(total - 1e-9);
    printf("%lld\n", ans);
    return 0;
}