题解:P11002 [蓝桥杯 2024 省 Python B] 神奇闹钟
P11002
传送门
Update on
-
本篇题解的 C++ 部分使用了标准库函数,由于较早版本 C++ 的标准库函数可能存在一些小问题,因此本篇题解无法在 C++98 或 C++14(GCC 9) 的编译选项下拿到满分。
-
Added Python 部分及代码。
思路
先考虑“已知输入时间的时间戳为
now ,如何求在这个时间之前最近一次闹铃响的时间戳”这个问题。不难得出,答案就是now - now \bmod 60x (意思就是用now 减去最后一次闹铃响了之后经过的时间)。
现在,只要实现时间字符串与时间戳的相互转化即可解决本题。如果直接手写,细节多且实现较麻烦。这时候,我们可以借助编程语言内置的处理时间的库来减小编码难度。
C++ 部分
我们可以借助 C++ 内置的 <time.h> 和 <sstream> 库来减小编码难度,具体如下:
- 将时间字符串转化为时间戳,这部分的代码如下:
time_t tostamp(string str){ istringstream ss(str); tm t; ss >> get_time(&t, "%Y-%m-%d %H:%M:%S"); //将字符串表示的时间直接转化成 tm 类型,方便后面操作 return mktime(&t);//将 tm 类型存储的时间转化为时间戳 } - 将时间戳转化为时间字符串,这部分的代码如下:
string todate(time_t sta){
tm* ptm = localtime(&sta);
//tm *localtime(const time_t *timer):将时间戳转化为tm类型。
ostringstream oss;
oss << put_time(ptm,"%Y-%m-%d %H:%M:%S");
return oss.str();
//上面三行:将 tm 类型存储的时间转化为字符串
}
关于以上出现的标准库函数与类型,如有不知道的,请自行 bdfs。
代码
#include<bits/stdc++.h>
using namespace std;
time_t tostamp(string str){
istringstream ss(str);
tm t;
ss >> get_time(&t, "%Y-%m-%d %H:%M:%S");
//将字符串表示的时间直接转化成 tm 类型,方便后面操作
return mktime(&t);//将 tm 类型存储的时间转化为时间戳
}
string todate(time_t sta){
tm* ptm = localtime(&sta);
//localtime():将时间戳转化为tm类型的本地时间
ostringstream oss;
oss << put_time(ptm,"%Y-%m-%d %H:%M:%S");
return oss.str();
//上面三行:将 tm 类型存储的时间转化为字符串
}
string s1,s2;
int x,T;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> T;
while(T--){
cin >> s1 >> s2 >> x; //读入的时间中间有空格,因此要用两个字符串先存着
x *= 60; // 时间戳是以秒为单位,而题目给的x是以分钟为单位的,所以要进行转化
string str = s1 + ' ' + s2;//还原为完整时间
time_t sta = tostamp(str);//将输入时间转化为时间戳
time_t ans = sta - sta % x;//求出答案时间戳
string res = todate(ans);//将答案时间戳转化为日期格式
cout << res << '\n';
}
return 0;
}
Python 部分
对于 Python 而言,我们可以使用 datetime 库来解决这个问题。由于前文以及代码里的注释已经讲的足够清晰了,因此不再赘述。
代码
from datetime import *
def solve(delta, str):
# 将传入的字符串转换为datetime类型
tm = datetime.strptime(str, '%Y-%m-%d %H:%M:%S')
# 起始时间设为 1970-01-01 00:00:00
st = datetime(1970, 1, 1)
# 计算现在的时间
now = tm - st
# 算出时间戳
tots = now.total_seconds()
# 用之前所述的公式计算答案时间戳
anss = tots - tots % delta
# 以下两行:将答案时间戳还原并返回
anst = st + timedelta(seconds=anss)
return anst.strftime('%Y-%m-%d %H:%M:%S')
t = int(input())
for i in range(t):
ymd, hms, delta = input().split()
delta = int(delta)
# 还原成完整时间并传入solve函数
ans = solve(delta * 60, ymd + ' ' + hms)
print(ans)