蓝桥杯[十一届][B组]-回文日期


一道经典而又稍微需要思考的题目,含有许多需要记住的东西

#include 
#include 
#include 
using namespace std;
// 月表 
int M[13]= {0,31,29,31,30,31,30,31,31,30,31,30,31};
// 获取回文数 
int getN(int n) {
    int ans=0;
    while(n) {
        ans=ans*10+n%10;
        n/=10;
    }
    return ans;
}
// 判断闰年 
bool isR(int n) {
    return n%400==0||(n%4==0&&n%100!=0);
}

// 根据年份返回一个合法的回文数
int makeS(int year) {
    int tmp=getN(year);
//    判断月份合法性
    if(tmp/100 <=0 || tmp/100 >12) {
        return -1;
    }
//    判断日期合法性
    if(tmp%100 <=0 || tmp%100 >M[tmp/100]) {
        return -1;
    }
//    特殊处理闰年的2,29日
// 如果不是闰年但日期是2月29日那么不合法
    if(tmp/100==2 && tmp%100 == 29 && !isR(year)) {
        return -1;
    }
    return year*10000+tmp;
}
int main() {
    int n;
    cin>>n;
//    遍历年:从当前年开始,因为可能回文日期就在当年
    int year;
    for(year=n/10000; year<=9999; year++) {
        int tmp=makeS(year);
        if(tmp!=-1) {
//            避免当前日期之前的日期出现 
            if(tmp>n){
                cout<endl;
                break; 
            }
        }
    }
    for(year=n/10000; year<=9999; year++) {
         int tmp=-1; 
         //        只有符合ABABBABA条件才会执行
        if(year/1000 == (year/10)%10 && (year/100)%10 == year%10){
            tmp=makeS(year);
        }
        if(tmp!=-1) {
            if(tmp>n){
                cout<<tmp;
                break;
            }
        }
    }

    return 0;
}