题解:P14497 [NCPC 2025] Crochet Competition
zybgml_AFO · · 题解
题号:P14497
题目链接:P14497 [NCPC 2025] Crochet Competition
题目简述:
题目给我们两个时间,让我们求出两个时间所差的时间并按要求输出。
思路:
这道题很显然,我们需要模拟计算加特判。具体过程分两步:
第一步,算出时差
两个时间都可以拆成三个部分:星期,时数和分数。
我们先打三个函数用于将字符串分解求时差:
inline string part_1(string x){
string z="";
for(int i=0;i<3;i++) z+=x[i];
return z;
}//拆出星期
inline int part_2(string x){
int z=0;
for(int i=4;i<6;i++) z=z*10+x[i]-'0';
return z;
}//拆出时数
inline int part_3(string x){
int z=0;
for(int i=7;i<9;i++) z=z*10+x[i]-'0';
return z;
}//拆出分数
可是现在还有一个问题。
我们拆出的第一部分,也就是星期,是一个字符串的形式。我们该如何将字符串转化为数字呢?
没错,用 map 映射可以轻松解决。我们只需要在开始初始化 map 就可以了。
w["Mon"]=1;w["Tue"]=2;w["Wed"]=3;w["Thu"]=4;w["Fri"]=5;w["Sat"]=6;w["Sun"]=7;
然后我们就可以利用以上代码在后续代码中求出时差了。
第二步,按要求分类讨论输出时差
此题的输出较为繁琐,为了方便,我们写几个便于输出的函数:
inline void print_1(int x){
if(x==1) printf("1 day");
else printf("%d days",x);
}//输出天数
inline void print_2(int x){
if(x==1) printf("1 hour");
else printf("%d hours",x);
}//输出时数
inline void print_3(int x){
if(x==1) printf("1 minute");
else printf("%d minutes",x);
}//输出分数
我们再来求时差。先将所有时间的单位都化为分钟,再去求时差较为方便:
int c1=w[part_1(a)]*1440+part_2(a)*60+part_3(a);//起始时间转换
int c2=w[part_1(b)]*1440+part_2(b)*60+part_3(b);//结束时间转换
int c=c2-c1;//求时差
可是如果出现
if(c<0) c+=10080;
我选择了最最最复杂的分类讨论。(不到万不得已别学我)
首先,我们分类讨论前得求出时差有几个部分。也就是需要输出几个值。可以用简单的运算求出:
int ans_1=c/1440,ans_2=(c%1440)/60,ans_3=c%60;
//三个值分别为天数,时数和分数。
我们分三类讨论:
第一类,时差共有一个部分
我们找一波哪个是需要输出的值,也就是排除掉
第二类,时差共有两个部分
我们只需要输出两个值。
找到唯一的
第三类,时差共有三个部分
直接照规则输出即可。(详见代码)
注意!
题目中说过:如果开始时间与结束时间完全相同,则比赛时长恰好为一整周。
千万要仔细读题!我就被坑了一回 QWQ。
解决此问题只需一个特判:
if(s1==s2) printf("7 days");
完整代码:
#include <bits/stdc++.h>
using namespace std;
map<string,int> w;
string s1,s2;
inline string part_1(string x){
string z="";
for(int i=0;i<3;i++) z+=x[i];
return z;
}
inline int part_2(string x){
int z=0;
for(int i=4;i<6;i++) z=z*10+x[i]-'0';
return z;
}
inline int part_3(string x){
int z=0;
for(int i=7;i<9;i++) z=z*10+x[i]-'0';
return z;
}
inline void print_1(int x){
if(x==1) printf("1 day");
else printf("%d days",x);
}
inline void print_2(int x){
if(x==1) printf("1 hour");
else printf("%d hours",x);
}
inline void print_3(int x){
if(x==1) printf("1 minute");
else printf("%d minutes",x);
}
inline void solve(string a,string b){
bool f=false;
if(w[part_1(a)]>w[part_1(b)]||(part_1(a)==part_1(b)&&part_2(a)*60+part_3(a)>part_2(b)*60+part_3(b))) f=true;
int c1=w[part_1(a)]*1440+part_2(a)*60+part_3(a);
int c2=w[part_1(b)]*1440+part_2(b)*60+part_3(b);
if(f) c2+=10080;
int c=c2-c1;
int ans_1=c/1440,ans_2=(c%1440)/60,ans_3=c%60;
if(ans_1==0&&ans_2==0) print_3(ans_3);
else if(ans_1==0&&ans_3==0) print_2(ans_2);
else if(ans_2==0&&ans_3==0) print_1(ans_1);
else if(ans_1==0){
print_2(ans_2);printf(" and ");print_3(ans_3);
}
else if(ans_2==0){
print_1(ans_1);printf(" and ");print_3(ans_3);
}
else if(ans_3==0){
print_1(ans_1);printf(" and ");print_2(ans_2);
}
else{
print_1(ans_1);printf(", ");print_2(ans_2);printf(", ");print_3(ans_3);
}
}
int main(){
w["Mon"]=1;w["Tue"]=2;w["Wed"]=3;w["Thu"]=4;w["Fri"]=5;w["Sat"]=6;w["Sun"]=7;
getline(cin,s1);
getline(cin,s2);
if(s1==s2) printf("7 days");
else solve(s1,s2);
return 0;
} //如要注释,可在上文中寻找代码块。
代码总结:
可见我的代码十分复杂,有很多累赘的东西。
可我还是认为,这样写比较方便。
因为这种题细节较多,这样写可以提高正确率。并且在出错时也能对症下药,方便检查。
题目总结:
这道题有许多细节要注意,并没有涉及一些其他的算法。只要基本功扎实,通过本题只是时间问题。可以用来练练手,刷刷手感。
题外话:
以上代码是为了写题解精简后的,我第一次过的代码 累赘更多)
可是写完之后还蛮有成就感的^_^。