每个屋顶独立往返一次,累加航行时间与上下船时间,最后向上取整。
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 个屋顶贡献
参考代码
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;
}