26行代码AC_试题 历届试题 日期问题 | 第八届蓝桥杯B组第七题
問題描述
??小明正在整理一批歷史文獻。這些歷史文獻中出現了很多日期。小明知道這些日期都在1960年1月1日至2059年12月31日。令小明頭疼的是,這些日期采用的格式非常不統一,有采用年/月/日的,有采用月/日/年的,還有采用日/月/年的。更加麻煩的是,年份也都省略了前兩位,使得文獻上的一個日期,存在很多可能的日期與其對應。
??比如02/03/04,可能是2002年03月04日、2004年02月03日或2004年03月02日。
給出一個文獻上的日期,你能幫助小明判斷有哪些可能的日期對其對應嗎?
輸入格式
一個日期,格式是"AA/BB/CC"。 (0 <= A, B, C <= 9)
輸出格式
輸出若干個不相同的日期,每個日期一行,格式是"yyyy-MM-dd"。多個日期按從早到晚排列。
樣例輸入
02/03/04
樣例輸出
2002-03-04
2004-02-03
2004-03-02
勵志用盡量少的代碼做高效表達
心路歷程
由于最近在備考藍橋杯,上午集訓隊比賽,堪堪A掉了一道日期題,讓我產生了訓練這一專題的想法, 于是找到了這道題。
首先覺得思路不難但是復雜,考慮點如下:
1、要分三種情況輸出
2、這三種情況中如果出現值相等的情況如何解決(如輸入02/02/02)。
3、在不同年份和月份下天數的變化情況。
第一遍敲了大概一百行,提交。一個樣例沒過,
網搜后看到一位大神的代碼,30多行就A掉了,于是學習,也做了一些改進。
對于考慮一:可以采用函數復用的方法,三合一,減少代碼量。
對于考慮二:每次判定完將結果存儲set容器中(有序且去重),最后直接輸出容器值
對于考慮三:考慮用一個二維數組把月份和天數關聯,這樣就不需要進行復雜的判定。
還需要特別注意日期為負的情況,栽在這里沒拿滿分。
直接貼代碼。
AC代碼(改進前)
#include<sstream> #include<iostream> #include<cstdio> #include<set> #include<string> using namespace std; set<string>s;int m[2][13] = {0,31,28,31,30,31,30,31,31,30,31,30,31,0,31,29,31,30,31,30,31,31,30,31,30,31};bool leap(int y) {if((y%4==0 && y%100) || y%400==0) return true;return false; }void check(int a, int b, int c) {char c1[15];if(a > 59 ) a+=1900;else a+= 2000;bool flag1 = false;if(b<=12 && b>=1) {if(b==1 || b==3 || b==5 || b==7 || b==8 || b==10 || b==12) {if(c<=31 && c>=1) flag1 = true;} else if(b==2) { //二月 if(leap(a)) {if(c<=29 && c>=1) flag1 = true; //閏年} else {if(c<=28 && c>=1) flag1 = true; }} else if(b==4 || b==6 || b==9 || b==11) { //30天的月份 if(c<=30 && c>=1) flag1 = true;}} if(flag1) {sprintf(c1,"%d-%02d-%02d",a,b,c);s.insert(c1);} } int main() {int a, b, c;scanf("%d/%d/%d", &a, &b, &c);check(a, b, c);check(c, a, b);check(c, b, a);for(set<string>::iterator it=s.begin(); it != s.end(); it++) cout << *it << endl;return 0; }可以看到,這段代碼即使做了函數復用,采用了set容器存儲,但沒有把月份和天數關聯在一個數組里,而是用if-else做多重判斷,因此顯著的增加了代碼量。
AC代碼(改進后)
#include<bits/stdc++.h> using namespace std; //當既需要判斷月份又需要判斷月份下的天數時,可以用數組關聯。 int m[2][13] = {0,31,28,31,30,31,30,31,31,30,31,30,31,0,31,29,31,30,31,30,31,31,30,31,30,31}; set<string>e;bool leap(int y) {if((y%4==0 && y%100) || y%400==0) return true; //y%100簡化 return false; }void check(int a, int b, int c) {char c1[15];if(a>59) a+=1900;else a+=2000;int f = 0; if(leap(a)) f=1; if(b>=1 && b<=12) if(c>=1 && c<=m[f][b]) { sprintf(c1, "%d-%02d-%02d", a, b, c); //打印 e.insert(c1);} }int main() {int a, b, c; scanf("%02d/%02d/%02d", &a, &b, &c); check(a,b,c); check(c,a,b); check(c,b,a);for(set<string>::iterator it=e.begin(); it!=e.end(); it++) cout << *it << endl; return 0;}如果這篇文章對你產生了幫助,就請給博主一個贊吧!大家的點贊是我創作的最大動力!
總結
以上是生活随笔為你收集整理的26行代码AC_试题 历届试题 日期问题 | 第八届蓝桥杯B组第七题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最全!最完整的递归下降分析法代码!!!
- 下一篇: 辗转相除法(欧几里得算法)求 最大公