本题要求给定一个初始日期时间(年、月、日、时)以及一个经过的小时数 (k),计算经过 (k) 小时后的日期和时间。数据保证初始时间是合法的,且 (k) 的范围很小((1 \le k \le 24)),年份范围在 2000 ~ 3000 之间。因此我们只需要依次处理小时、日、月、年的进位即可,不需要复杂的大范围日期计算。
在日期计算中,一个容易出错的点是不同月份的天数不同,尤其是 2 月份在闰年和平年的天数不同。题目已经给出了闰年判断规则:
满足上述任意一条即为闰年,否则为平年。
由于 (k) 最大只有 24 小时,并且初始小时 (h) 的范围为 0~23,因此 (h + k) 最大为 47,最多只会跨 1 天(不可能连续跨多天)。我们可以分三步进行进位处理:
这样处理后,就能得到正确的结果。由于数据范围很小,不需要考虑循环多次进位。
具体实现时,我们可以:
h += k。h >= 24,则 h -= 24,d += 1。m 和年份 y 计算当月最大天数 days:
d > days,则 d -= days,m += 1。m > 12,则 m = 1,y += 1。这样,用非常清晰的模拟方式即可解决问题。
算法中只进行了常数次的判断和赋值操作,不涉及任何循环或递归,因此时间复杂度为 (O(1)),空间复杂度也为 (O(1))。完全满足题目的时间限制。
下面给出修正后的 C++ 代码(原参考代码有一处语法错误,已修正):
cpp1#include <iostream> 2using namespace std; 3 4int main() { 5 int y, m, d, h, k; 6 cin >> y >> m >> d >> h >> k; 7 8 // 小时进位 9 h += k; 10 if (h >= 24) { 11 h -= 24; 12 d += 1; 13 14 // 计算当前月份的天数 15 int days = 0; 16 if (m == 1 || m == 3 || m == 5 || m == 7 || m == 8 || m == 10 || m == 12) { 17 days = 31; 18 } else if (m == 4 || m == 6 || m == 9 || m == 11) { 19 days = 30; 20 } else if (m == 2) { 21 // 闰年判断 22 if ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0)) { 23 days = 29; 24 } else { 25 days = 28; 26 } 27 } 28 29 // 日期进位 30 if (d > days) { 31 d -= days; 32 m += 1; 33 // 月份进位 34 if (m > 12) { 35 m = 1; 36 y += 1; 37 } 38 } 39 } 40 41 cout << y << " " << m << " " << d << " " << h << "\n"; 42 return 0; 43}
本题考察的是对时间进位的简单模拟以及闰年的判断。由于数据范围非常小,不需要复杂的计算,只需按部就班处理小时 → 日 → 月 → 年的进位即可。掌握好月份天数规则和闰年条件,就能轻松 AC。