第八届蓝桥杯第七题--日期问题(C语言)

第八届蓝桥杯第七题–日期问题(C语言)

(这是我自己对该问题的一点见解和分析,因为新手菜鸟级,所以很多不好的,值得改进的地方欢迎提出,谢谢)

一.比赛题目

1.题目要求

小明正在整理一批历史文献。这些历史文献中出现了很多日期。小明知道这些日期都在1960年1月1日至2059年12月31日。令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的,有采用月/日/年的,还有采用日/月/年的。更加麻烦的是,年份也都省略了前两位,使得文献上的一个日期,存在很多可能的日期与其对应。
比如02/03/04,可能是2002年03月04日、2004年02月03日或2004年03月02日。
给出一个文献上的日期,你能帮助小明判断有哪些可能的日期对其对应吗?

2.输入与输出

输入:一个日期,格式是"AA/BB/CC"。 (0 <= A, B, C <= 9)

输出:输出若干个不相同的日期,每个日期一行,格式是"yyyy-MM-dd",多个日期按从早到晚排列。

样例输入:
02/03/04

样例输出:
2002-03-04
2004-02-03
2004-03-02

二.分析过程

1.整体分析

错误分析:当时一看到这题目我就想的是挨个挨个从三种时间(年/月/日,月/日/年,日/月/年)上去分析,但是写了一通下来发现代码是又长又乱,写着写着自己都会糊涂
现在进入正式分析:(1)首先经过分析我发现组合出来只有六种情况:

AA为年 CC为年(19) CC为年(20)
19AA-BB-CC 19CC-AA-BB 20CC-AA-BB
20AA-BB-CC 19CC-BB-AA 20CC-BB-AA

所以设置三个数组来存放
代码如下(我觉得对于这段代码没有处理得很好,但是目前暂时没有想到更好的简化方法,希望如果能够有大神看到并提出解决更好,谢谢!):

	//#define N 6
	int a,b,c,i;
	scanf("%d/%d/%d",&a,&b,&c);		
			//输入AA,BB,CC;
	int a1[N],b1[N],c1[N];			
		//三个数组分别来装六种情况
		//年(a1[]),月(b1[]),日(c1[]);
	a1[0]=1900+a;
	b1[0]=b;
	c1[0]=c;
	
	a1[1]=2000+a;
	b1[1]=b;
	c1[1]=c;
	
	a1[2]=1900+c;
	b1[2]=a;
	c1[2]=b;
	
	a1[3]=1900+c;
	b1[3]=b;
	c1[3]=a;
	
	a1[4]=2000+c;
	b1[4]=a;
	c1[4]=b;
	
	a1[5]=2000+c;
	b1[5]=b;
	c1[5]=a;
		//列出六种情况

(2)然后在上面全排列的基础上在进行条件筛选
年的数组a1[ ]在1960–2059;
月的数组b1[ ]在1–12;
日的数组c1[ ]在1-31等;
在此特别注意日的数组有大月和小月之分,也特别要小心闰年的二月和平年的二月之分;
代码如下:

for(i=0;i<N;i++)
	{
		if(a1[i]<1960||a1[i]>2059||b1[i]>12||c1[i]>31||b1[i]<=0||c1[i]<=0)
		{
			a1[i]=0;
			b1[i]=0;
			c1[i]=0;
		}
		else if(b1[i]==2&&((a1[i] % 4 == 0) && (a1[i] % 100 != 0) || (a1[i] % 400 == 0))&&c1[i]>29)
		{
			a1[i]=0;
			b1[i]=0;
			c1[i]=0;
		}
		else if(b1[i]==2&&
		((a1[i]%4!=0&&a1[i]%100==0)||(a1[i]%400!=0))&&c1[i]>28)
		{
			a1[i]=0;
			b1[i]=0;
			c1[i]=0;
		}
		else if((b1[i]==2||b1[i]==4||b1[i]==6||b1[i]==9||b1[i]==11)&&c1[i]>30)
		{
			a1[i]=0;
			b1[i]=0;
			c1[i]=0;
		}
	}		
	//将上述所有不满足条件的年月日都赋值变为0来区别开;

(3)在筛选完成后,因为题目要求从小到大排序,所以下一步我们进行排序
因为数组不大,所以就本题而言基本上采用何种排序方法都不会超过题目的时间和空间限制;但是当数组很大的时候,就要开始考虑排序的时间和空间复杂度了。
代码如下:

int swap(int *a,int *b)
{
	int n;
	n=*a;
	*a=*b;
	*b=n;
	return 0;
}		
	//因为交换的次数会非常多
	//为了避免多次书写,就单独写了一个函数出来调用;
for(i=0;i<N-1;i++)
	{
		for(int j=i+1;j<N;j++)
		{
			if(a1[i]>a1[j])
			{
				swap(&a1[i],&a1[j]);
				swap(&b1[i],&b1[j]);
				swap(&c1[i],&c1[j]);
			}
			else if(a1[i]==a1[j])
			{
				if(b1[i]>b1[j])
				{
					swap(&b1[i],&b1[j]);
					swap(&c1[i],&c1[j]);	
				}
				else if(b1[i]==b1[j])
				{
					if(c1[i]>c1[j])
					{
						swap(&c1[i],&c1[j]);
					}
					else if(c1[i]==c1[j])
					{
						a1[i]=0;
						b1[i]=0;
						c1[i]=0;
					}	//保证相同的只会输出一次
				}
			}
		}
	}
	//依次从年月日来进行比较,从小到大排列
	//交换,最后最小的在最左边,最大的在最右边,形成有序

(4)最后进行输出
输出的时候注意,因为小于10的日,月前面是要求加上0来输出的,所以在输出的时候也要有条件。
代码如下:

for(i=0;i<N;i++)
	{
		if(a1[i]!=0)
		{
			if(b1[i]>9&&c1[i]>9)
				printf("%d-%d-%d\n",a1[i],b1[i],c1[i]);
			else if(b1[i]>9&&c1[i]<=9)
				printf("%d-%d-0%d\n",a1[i],b1[i],c1[i]);
			else if(b1[i]<=9&&c1[i]>9)
				printf("%d-0%d-%d\n",a1[i],b1[i],c1[i]);
			else if(b1[i]<=9&&c1[i]<=9)
				printf("%d-0%d-0%d\n",a1[i],b1[i],c1[i]);
		}			
	}

三.整体代码

#include
#define N 6
int swap(int *a,int *b)
{
	int n;
	n=*a;
	*a=*b;
	*b=n;
	return 0;
}
				//交换 
int main()
{
	int a,b,c,i;
	scanf("%d/%d/%d",&a,&b,&c);
	int a1[N],b1[N],c1[N];
	a1[0]=1900+a;
	b1[0]=b;
	c1[0]=c;
	
	a1[1]=2000+a;
	b1[1]=b;
	c1[1]=c;
	
	a1[2]=1900+c;
	b1[2]=a;
	c1[2]=b;
	
	a1[3]=1900+c;
	b1[3]=b;
	c1[3]=a;
	
	a1[4]=2000+c;
	b1[4]=a;
	c1[4]=b;
	
	a1[5]=2000+c;
	b1[5]=b;
	c1[5]=a;
			//将六种情况赋值 
	for(i=0;i<N;i++)
	{
		if(a1[i]<1960||a1[i]>2059||b1[i]>12||c1[i]>31||b1[i]<=0||c1[i]<=0)
		{
			a1[i]=0;
			b1[i]=0;
			c1[i]=0;
		}
		else if(b1[i]==2&&((a1[i] % 4 == 0) && (a1[i] % 100 != 0) || (a1[i] % 400 == 0))&&c1[i]>29)
		{
			a1[i]=0;
			b1[i]=0;
			c1[i]=0;
		}
		else if(b1[i]==2&&((a1[i]%4!=0&&a1[i]%100==0)||(a1[i]%400!=0))&&c1[i]>28)
		{
			a1[i]=0;
			b1[i]=0;
			c1[i]=0;
		}
		else if((b1[i]==2||b1[i]==4||b1[i]==6||b1[i]==9||b1[i]==11)&&c1[i]>30)
		{
			a1[i]=0;
			b1[i]=0;
			c1[i]=0;
		}
	}
			//将不符合条件的数组赋值为0 
	for(i=0;i<N-1;i++)
	{
		for(int j=i+1;j<N;j++)
		{
			if(a1[i]>a1[j])
			{
				swap(&a1[i],&a1[j]);
				swap(&b1[i],&b1[j]);
				swap(&c1[i],&c1[j]);
			}
			else if(a1[i]==a1[j])
			{
				if(b1[i]>b1[j])
				{
					swap(&b1[i],&b1[j]);
					swap(&c1[i],&c1[j]);	
				}
				else if(b1[i]==b1[j])
				{
					if(c1[i]>c1[j])
					{
						swap(&c1[i],&c1[j]);
					}
					else if(c1[i]==c1[j])
					{
						a1[i]=0;
						b1[i]=0;
						c1[i]=0;
					}
				}
			}
		}
	}
			//排序
	for(i=0;i<N;i++)
	{
		if(a1[i]!=0)
		{
			if(b1[i]>9&&c1[i]>9)
				printf("%d-%d-%d\n",a1[i],b1[i],c1[i]);
			else if(b1[i]>9&&c1[i]<=9)
				printf("%d-%d-0%d\n",a1[i],b1[i],c1[i]);
			else if(b1[i]<=9&&c1[i]>9)
				printf("%d-0%d-%d\n",a1[i],b1[i],c1[i]);
			else if(b1[i]<=9&&c1[i]<=9)
				printf("%d-0%d-0%d\n",a1[i],b1[i],c1[i]);
		}			
	}
			//四种情况的输出 
	return 0;
}

四.总结

这道题算是我想着觉得挺简单,结果做了半天越做越复杂,理不顺,然后自己水平也有限,在博客里面看其他人的文章,觉得都是神仙操作,眼睛:我行了,手:不可 (我太菜了,对不起),最后就突然来了灵感的一道题。写出来并通过了之后觉得有时候换个思路其实挺重要的,换个思路想不就出来了嘛。这篇文章写出来也是想着自己能够收获和学习的,所以代码有很多没有做到简化,也不够好的地方,希望各位大大们能够多多提出意见和建议,谢谢!

你可能感兴趣的:(蓝桥杯题)