蓝桥杯题库 回文日期
题目描述
2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2 日。因为如果将这个日期按 “yyyymmdd” 的格式写成一个 8 位数是 20200202,恰好是一个回文数。我们称这样的日期是回文日期。
有人表示 20200202 是 “千年一遇” 的特殊日子。对此小明很不认同,因为不到 2 年之后就是下一个回文日期:20211202 即 2021 年 12 月 2 日。
也有人表示 20200202 并不仅仅是一个回文日期,还是一个 ABABBABA 型的回文日期。对此小明也不认同,因为大约 100 年后就能遇到下一个 ABABBABA 型的回文日期:21211212 即 2121 年 12 月 12 日。算不上 “千年一遇”,顶多算 “千年两遇”。
给定一个 8 位数的日期,请你计算该日期之后下一个回文日期和下一个 ABABBABA 型的回文日期各是哪一天。
输入描述
输入包含一个八位整数 ,表示日期。
对于所有评测用例,保证 是一个合法日期的 8 位数表示。
输出描述
输出两行,每行 1 个八位数。第一行表示下一个回文日期,第二行表示下一个 ABABBABA 型的回文日期。
输入输出样例
示例
输入
20200202
输出
20211202
21211212
解题思路:
这道题也是想了比较久的时间(大概三~四个小时),尝试过很多方法,不过不得不说也是受益匪浅,
首先我尝试的还是经典但又笨拙的老办法,用字符串存储初始日期,再进行分割然后直接用string库中自带的reverse(str1.begin(),str1.end())函数来对该日期字符串进行颠倒,然后判断颠倒前和颠倒后字符串是否相同,如果相同则说明为回文日期,但是不知道哪里出错了一直无法实现(可能是后面的原因,这个思路是否正确我还没有深究,现在粗略思考一下,用来判断是否为回文数应该还是可以的,但是无法判断是否为ABABBABA类型回文数),所以我改变了思路,虽然还是使用string类型去存储,但是判断回文用指定字符串位置进行判断,因为题中说了固定就是八个数字且必为合法数字,只需要将输入的日期转为字符串,然后判断指定位数是否相同即可,例如在判断是否为回文时只需要判断是否字符串第0位与第七位和第一位与第六位和第二位与第五位和第三位与第四位是否分别相等,若相等,则说明为回文,而在判断是否为ABABBABA类型的回文日期时则判断字符串第零位与第二位和第五位和第七位和第一位与第三第四与第六位是否都相等就行。若符合条件,则输出,若不符合条件,因为其是字符串类型,在遍历日期方面上有所不足,所以我用用了另一个整形变量date去存储日期的int类型,这样在程序运行时包括在while内部时temp和date总能分别代表当前正在遍历的日期的整型和字符串类型,在进行下一条件时只需要将int类型的日期+1后转化为string赋值给temp即可实现遍历。
同时题目中需要特别注意的一点是必须要去判断日期的合理性,不可能出现20244202这燕子的回文日期。所以我将bool check() 即为日期判断是否合法函数放在最上面定义,同时要在日期开始遍历之前就判断当前经过上一次循环+1后的int类型的日期是否合法,且一定要放在while循环中较前的位置,避免任何一次错误遍历,因为在一次一次的遍历中,非法日期远大于仅有365天的合法日期。
最后也是最关键的一点,也是我想了很久的,最后不得不去求助我哥。就是关于在if条件中的连等的时候情况,可以在下面看到我的代码中在判断回文和ABABBABA类型回文时都对string类型做了是否连等判断,但是其中总是出问题,后来才知道,在C++中,类似 “a==b==c" 这样的表达式,会先判断a==b的结果,若a==b为假,则结果为0,若为真,则结果为1,所以与c判断的左边的值仅仅为0或1,就这一点困扰了我做这道题目的一大半的时间,最后只能不断利用&&和==0去对判断条件做不断修改。具体可以看代码中的表现形式。
其中还有一个应该说目前对我而言已经可以熟练运用的就是在一次循环内选择性的多次输出问题,都是利用定义一个flag变量等于零 去进行调整,例如本题中,在判断得到第一个回文日期并输出后,由于该回文日期可能并非ABABBABA类型回文,需要日期+1之后重新遍历,那么可能又要输出一次普通回文日期,那就不符合题目要求,所以在输出一次普通回文日期之后标记flag为1,而出发输出普通回文日期除了满足当前日期为回文日期之外同时满足flag为0,则可以避免重复输出普通回文日期的情况。
还有一个不是很重要的一个点吧,就是我以为日期判断会很麻烦,包括有部分题解也是这么说的,但是我发现好像写个bool check真的不算是很难的东西,也就是对日期合法性的判断并没有预想中的那么麻烦,不必过于担心。
My code(有详细批注):
#include<bits/stdc++.h> //万能库
using namespace std;
//Designed By Xu
bool check(int num1) //日期合法性判断函数
{
int year,month,day,date;
int monday[]={0,31,2,31,30,31,30,31,31,30,31,30,31}; //规定每月天数
year=num1/10000; //分离处年份
month=num1/100-year*100; //分离出月份
day=num1%100; //分离出日期
if(year%4==0) //如果当前年份为闰年
{
monday[2]==28; //将二月修改为28天
if(day>monday[month]) //如果天数超过当月最大天数
{
return false; //日期不合法
}
if(month>12) //如果月份大于12,说明日期不合法
{
return false; //表示不合法日期
}
return true; //日期合法
}
else
{
monday[2]==29;
if(day>monday[month]) //若为闰年则再做当月天数和月份最大值判断。
{
return false; //日期不合法 日超过当月最大日
}
if(month>12)
{
return false; //日期不合法 月份超过12
}
return true; //日期合法
}
}
bool hui(string num2) //回文日期判断
{
if( (num2[0]==num2[7]) && (num2[1]==num2[6]) && (num2[2]==num2[5] && (num2[3]==num2[4]) ) ) //判断对应位置是否相等
{
return true; //回文 返回true
}
return false; //非回文 返回false
}
bool huiab(string num3) //ABABBABA类型回文日期判断
{
if( ((num3[0]==num3[2])==1) && ((num3[7]==num3[2])==1) && ((num3[5]==num3[7])==1) && ((num3[1]==num3[3])==1) && ((num3[4]==num3[6])==1) && ((num3[3]==num3[4])==1) ) //判断对应位置是否相等
{
return true; //符合ABABBABA类型回文,返回true
}
return false; //不符合ABABBABA类型回文,返回false
}
int main()
{
int date,year,month,day;
int flag=0,flag2;
string temp;
cin>>date;
while(1) //定义死循环遍历
{
date += 1; //开始八位数遍历
temp=to_string(date); //同步将该八位数转化为一个字符串存储
if(!check(date)) //判断该八位数作为日期是否合法
{
continue; //若不合法则结束当次循环,进入下一次while
}
if(hui(temp)) //判断是否为普通回文日期
{
if(flag==0) //因为普通回文日期只需打印一次,而后还要继续遍历ABABBABA类型回文,不能在每次遍历ABABBABA类型的时候都输出,所以用flag作为标记达到输出一次普通回文日期之后就不再输出的效果
{
cout<<temp<<endl; //输出下一个普通回文日期
flag=1; //flag==1标记,下一次遍历到普通回文不再输出
}
if(huiab(temp)) //判断是否为ABABBABA类型回文日期
{
cout<<temp<<endl; //输出ABABBABA类型回文日期
return 0; //两个回文日期输出,程序结束。
}
}
}
}

添加 家长论坛微信
全部 0条评论