一、先看原题:


二、读懂题目:
时间格式是 HH:MM,我们要找下一个 回文时间 (形如 ab:ba,即小时的两个数字倒过来就是分钟的两个数字)。
所以:把小时的十位和个位互换成分钟,若分钟合法(0..59)且时间在给定时间之后,则就是一个候选答案。从现在起顺时针往后看每个小时(最多看 24 个小时),第一个满足条件的就是答案。
三、关键点:
-
回文时间定义是
HH:MM形式且MM等于把HH的两位数倒过来(比如13→31,对应时间13:31)。 -
在 24 小时制下,只要
MM < 60才合法。把00~23的小时翻转后,合法的小时有:
00,01,02,03,04,05,10,11,12,13,14,15,20,21,22,23,对应的回文时间为:
00:00, 01:10, 02:20, 03:30, 04:40, 05:50, 10:01, 11:11, 12:21, 13:31, 14:41, 15:51, 20:02, 21:12, 22:22, 23:32 -
处理步骤:读入当前时间(
HH:MM),把它转换为"从午夜起的分钟数";把数组中每个回文时间也转换为分钟数;找到第一个严格大于当前分钟数的回文时间并输出;如果找不到(当天都没有更晚的回文时间),输出00:00(即第二天的第一个回文时间)。
四、参考程序1:(预设比较法)
cpp
#include <bits/stdc++.h>
using namespace std;
// 把 "HH:MM" 转换成 从午夜起的分钟数(0..1439)
int timeToMinutes(const string &t) {
int hh = stoi(t.substr(0,2));
int mm = stoi(t.substr(3,2));
return hh * 60 + mm;
}
int main() {
string cur;
cin >> cur; // 读取 "HH:MM"
// 预先列出一天内按时间顺序的所有回文时间
vector<string> pal = {
"01:10","02:20","03:30","04:40","05:50",
"10:01","11:11","12:21","13:31","14:41","15:51",
"20:02","21:12","22:22","23:32"
};
int now = timeToMinutes(cur);
// 找第一个严格在当前时间之后的回文时间
for (const string &p : pal) {
if (timeToMinutes(p) > now) {
cout << p << '\n';
return 0;
}
}
// 当天没有则输出第二天最早的回文时间(即 00:00)
cout << "00:00\n";
return 0;
}
五、程序1的说明:
-
把回文时间写出来放好 (就像把你喜欢的卡片排好队)
我们把这 15 个回文时间排在
pal向量里,顺序是从01:10到23:32,就像一日时间的顺序。 -
把输入时间转换成"分钟" (把时间换算成一个数字,方便比较)
例如
13:31→13*60 + 31 = 811分钟。 -
逐个去数组里比较:
-
看
pal[0](00:00)对应的分钟数是不是 > 当前分钟数?如果是,就输出它; -
否则继续看
pal[1],依次往后; -
如果数组走完了都没有找到(说明今天剩下的时间里没有更晚的回文时间),就输出
00:00(第二天的第一个回文时间)。
-
-
为什么不包含当前时刻?
题目要求"在此之后(不包含此刻)",所以如果输入本身就是回文时间(比如输入
13:31),程序不会输出13:31,而是会输出下一次的回文时间(这里是14:41,因为在数组里13:31后面就是14:41)
六、参考程序2:(模拟翻转法)
cpp
#include <bits/stdc++.h>
using namespace std;
// 把一个两位数左右翻转,例如 23 -> 32
int flip(int x) {
int a = x / 10;
int b = x % 10;
return b * 10 + a;
}
int main() {
string s;
cin >> s; // 输入格式 "HH:MM"
int H = stoi(s.substr(0, 2));
int M = stoi(s.substr(3, 2));
for (int h = H; h <= 23; h++) {
int m = flip(h); // 翻转小时得到分钟
if (m < 60) { // 分钟必须合法
if (h > H || m > M) { // 必须是当前时间之后
printf("%02d:%02d\n", h, m);
return 0;
}
}
}
// 如果一天中没找到,下一天的第一个回文时间一定是 00:00
cout << "00:00\n";
return 0;
}
七、程序2的说明:
1、书写翻转函数:
cpp
// 把一个两位数左右翻转,例如 23 -> 32
int flip(int x) {
int a = x / 10;
int b = x % 10;
return b * 10 + a;
}
-
flip()把小时的两个数字互换顺序。 -
示例:
-
flip(23):a=2, b=3→ 返回32。 -
flip(5):a=0, b=5→ 返回50(表示05小时对应分钟50,时间05:50)。
-
-
想像把小时放到镜子里,镜子里的数字就是函数返回的结果。
2、转换字符串为 整型:
cpp
int H = stoi(s.substr(0, 2));
int M = stoi(s.substr(3, 2));
-
把输入字符串拆开:
-
s.substr(0,2)取前两位(小时的两位,例如"12"),用stoi变成整数12,放到H。 -
s.substr(3,2)取后两位(分钟"21"),变成整数21,放到M。
-
-
假如输入
"05:07",则H=5,M=7。
> 小提醒:这个写法要求输入必须是 HH:MM 的格式(两位小时,两位分钟,中间有冒号)。题目保证了这一点。
3、程序的核心逻辑:
cpp
for (int h = H; h <= 23; h++) {
int m = flip(h); // 翻转小时得到分钟
if (m < 60) { // 分钟必须合法
if (h > H || m > M) { // 必须是当前时间之后
printf("%02d:%02d\n", h, m);
return 0;
}
}
}
(1)for (int h = H; h <= 23; h++)
-
从当前小时
H开始,检查H, H+1, H+2, ...一直到23(当天最后一小时)。 -
我们只检查当天剩下的小时,因为如果当天找不到再处理第二天的
00:00。
(2)int m = flip(h);
把小时 h 翻转,得到相应的"回文分钟" m。例如 h=13 → m=31。
(3)if (m < 60)
分钟必须是合法的分钟(0 到 59)。有些小时翻转后会得到 61、71 等不合法的分钟,就要跳过(例如 16 → 61 不合法)。
(4)if (h > H || m > M)
-
这句是确保严格在当前时间之后:
-
如果
h > H,说明我们检查的是比当前小时更晚的小时(比如当前H=12,现在h=13),那么任何合法的m都在之后,可以直接接受。 -
如果
h == H(第一圈),则需要m > M,保证分钟比当前分钟晚(因为题目不包含当前刻)。
-
-
这样就能保证找到的时间是"下一次"回文时间,不会返回当前时刻本身。
(5)printf("%02d:%02d\n", h, m);
找到后用 printf 输出,例如 05:50,%02d 确保两位显示,不足补 0(5 会显示为 05)
(6)return 0;
找到答案就结束程序,不继续循环。
4、如果循环结束没找到,就输出 "00:00":
cpp
// 如果一天中没找到,下一天的第一个回文时间一定是 00:00
cout << "00:00\n";
return 0;
}
八、总结:
1、预设比较法:
把"小时"照镜子变成分钟:
-
ab:ba是回文时间; -
有效小时(翻转后分钟 < 60)只有这些:
00,01,02,03,04,05,10,11,12,13,14,15,20,21,22,23。记住这 16 个就够用了!
2、模拟反转法:
-
把小时照镜子得到分钟(
flip)。 -
如果镜像分钟合法(<60)并且时间比现在晚(严格大于),那就是答案。
-
从当前小时往后一小时一小时地试,试到 23 还没找到就输出
00:00。