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
#include
#include
#include
#include
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
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;} 


如果这篇文章对你产生了帮助,就请给博主一个赞吧!大家的点赞是我创作的最大动力!

你可能感兴趣的:(日期专题,蓝桥杯,算法,数据结构,蓝桥杯,acm竞赛,c++)