题解:洛谷 P5707 上学迟到
【题目来源】
【题目描述】
学校和 yyy 的家之间的距离为 \(s\) 米,而 yyy 以 \(v\) 米每分钟的速度匀速走向学校。
在上学的路上,yyy 还要额外花费 \(10\) 分钟的时间进行垃圾分类。
学校要求必须在上午 \(8:00\) 到达,请计算在不迟到的前提下,yyy 最晚能什么时候出门。
由于路途遥远,yyy 可能不得不提前一点出发,但是提前的时间不会超过一天。
【输入】
一行两个正整数 \(s,v\),分别代表路程和速度。
【输出】
输出一个 \(24\) 小时制下的时间,代表 yyy 最晚的出发时间。
输出格式为 HH:MM,分别代表该时间的时和分。必须输出两位,不足前面补 \(0\)。
【输入样例】
100 99
【输出样例】
07:48
【核心思想】
-
问题分析:给定距离 \(s\) 米、速度 \(v\) 米/分钟,yyy 需要 \(10\) 分钟进行垃圾分类,必须在 \(8:00\) 到达学校。求最晚出发时间(24 小时制,格式 HH:MM)。这是一个时间倒推计算问题。
-
算法选择:
- 向上取整计算耗时:路程时间 = \(\lceil s / v \rceil\),加上垃圾分类 \(10\) 分钟得到总耗时 \(t\)
- 时间倒推:从 \(8:00\) 倒推 \(t\) 分钟,处理跨天情况(提前不超过一天)
-
关键步骤:
- 读入数据:
cin >> s >> v - 计算总耗时:
t = s / v + 10:基础路程时间(整数除法向下取整)加 \(10\)- 若
s % v != 0:t++,向上取整(不足一分钟按一分钟算)
- 时间倒推:
- 初始化
x = 8, y = 0(目标时间 8:00) - 当
t > y时循环(需要借小时):- 若
x == 0:跨天,x = 24 x--(小时减 1),y += 60(分钟加 60)
- 若
y = y - t(剩余分钟即为出发分钟)
- 初始化
- 格式化输出:
- 小时和分钟均不足两位时前面补 \(0\)
- 读入数据:
-
时间/空间复杂度:
- 时间复杂度:\(O(t/60)\),最多循环 24 次(一天内)
- 空间复杂度:\(O(1)\),仅需常数个变量
-
时间计算的核心思想:
- 向上取整处理:
s % v != 0时时间加 1,确保"不足一分钟按一分钟计" - 借位倒推:从目标时间倒推,分钟不够减时向小时借位(1 小时 = 60 分钟)
- 跨天处理:
x减到 0 时回到 24,保证提前不超过一天的约束 - 格式化补零:分别判断小时和分钟是否 \(\ge 10\),不足则前面补 \(0\)
- 适用于时间计算、倒计时、格式化输出类问题
- 向上取整处理:
【算法标签】
普及- #模拟
【代码详解】
#include <bits/stdc++.h> // 包含标准库头文件(万能头文件)
using namespace std; // 使用标准命名空间
/**
* 主函数 - 程序入口
* @return 程序执行状态码(0表示成功)
*/
int main()
{
int s, v; // 定义变量:距离s(米),速度v(米/分钟)
cin >> s >> v; // 输入距离和速度
int x = 8, y = 0; // 初始化出发时间:8:00(x小时y分钟)
int t = s / v + 10; // 计算基本时间 = 路程时间 + 10分钟缓冲
// 处理不足1分钟的情况
if (s % v != 0)
{
t++; // 如果有余数,时间加1分钟
}
// 计算最晚出发时间(倒推时间)
while (t > y)
{
if (x == 0) // 处理跨天情况
{
x = 24; // 从24点(0点)开始倒推
}
x--; // 小时减1
y += 60; // 分钟加60(借1小时)
}
y = y - t; // 计算剩余分钟数
// 格式化输出时间(保证两位数显示)
if (x >= 10)
{
if (y >= 10)
{
cout << x << ":" << y << endl; // 小时和分钟都两位数
}
else
{
cout << x << ":0" << y << endl; // 小时两位数,分钟补零
}
}
else
{
if (y >= 10)
{
cout << "0" << x << ":" << y << endl; // 小时补零,分钟两位数
}
else
{
cout << "0" << x << ":0" << y << endl; // 小时和分钟都补零
}
}
return 0; // 返回程序执行成功状态码
}
【运行结果】
100 99
07:48
浙公网安备 33010602011771号