蓝桥杯2017初赛:日期问题(STL结构体排序和unique函数去重)

[蓝桥杯2017初赛]日期问题

  • Description

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

  • Input

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

  • Output

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

分析

这个题不难,但是非常的麻烦,呜呜呜本菜鸟写了3个小时才改好。
题目只有三种格式,y/m/d,m/d/y,d/m/y。而年份有2种情况,19XX和20XX,由于输入格式为AA/BB/CC,所以对于每一种格式,分别判断1900+AA和2000+AA即可,当AA,BB,CC都相同时,则涉及到去重问题

STL自定义排序
2种方式:

第一种,直接在定义结构体时重载小于号运算符,这种方式排序时还是正常写法:
bool operator<(const node &a)  //重载小于号,方便排序
    {
       if((*this).y!=a.y)       //年份不同,直接比较年份
          return (*this).y<a.y;
       else if((*this).m!=a.m)         //年份不同,比较月份
          return (*this).m<a.m;
       else                                  //y和m都相等
          return (*this).d<a.d;
    }
sort(v,begin(),v.end())
第二种,在结构体外写一个比较函数,这种方式排序时要加上函数名
bool cmp(node a,node b)   //自定义排序
{
    if(a.y!=b.y)
        return a.y<b.y;
    else if(a.m!=b.m)         //a.y=b.y
        return a.m<b.m;
    else                      //y和m都相等
        return a.d<b.d;
}
sort(v,begin(),v.end(),cmp)

STL结构体去除重复项

对于vector容器,排序后使用v.erase(unique(begin(v), end(v)), end(v))语句
即可去重重复项,但对于结构体而言,首先要重载“==”运算符
貌似set容器在结构体里重载运算符更简单?

bool operator==(const node&a)  //重载等于号,方便结合unique去重
{
     return (*this).y==a.y&&(*this).m==a.m&&(*this).d==a.d;
}
v.erase(unique(begin(v), end(v)), end(v))
  • AC代码
#include <bits/stdc++.h>
using namespace std;
struct node   //定义结构体
{
    int y,m,d;
    node(int yy,int mm,int dd):y(yy),m(mm),d(dd){}
    bool operator<(const node &a)  //重载小于号,方便排序
    {
       if((*this).y!=a.y)       //年份不同,直接比较年份
          return (*this).y<a.y;
       else if((*this).m!=a.m)         //年份不同,比较月份
          return (*this).m<a.m;
       else                                  //y和m都相等
          return (*this).d<a.d;
    }
    bool operator==(const node&a)  //重载等于号,方便结合unique去重
    {
        return (*this).y==a.y&&(*this).m==a.m&&(*this).d==a.d;
    }
};
//结合判断闰年,直接返回y年m月的日期
int a[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)   //判断闰年
{
    return y%4==0&&y%100!=0||y%400==0;
}
bool ok(int y,int m,int d) //判断年月日是否在给定范围内
{
    if(y>=1960&&y<=2059&&m>=1&&m<=12&&d>=1&&d<=a[leap(y)][m])
        return 1;
    return 0;
}
bool cmp(node a,node b)   //自定义排序 --没用到
{
    if(a.y!=b.y)
        return a.y<b.y;
    else if(a.m!=b.m)         //a.y=b.y
        return a.m<b.m;
    else                      //y和m都相等
        return a.d<b.d;
}
int main()
{
    vector<node>v;
    int y,m,d;
    char ch;
    cin>>y>>ch>>m>>ch>>d;
                               //讨论 y/m/d 的情况
    int y1=1900+y,m1=m,d1=d;
    if(ok(y1,m1,d1))//结合判断闰年,直接返回y年m月的日期
        v.push_back(node(y1,m1,d1));
    y1=2000+y;
    if(ok(y1,m1,d1))
        v.push_back(node(y1,m1,d1));
                               //讨论 m/d/y 的情况
    int y2=1900+d,m2=y,d2=m;
    if(ok(y2,m2,d2))
        v.push_back(node(y2,m2,d2));
    y2=2000+d;
    if(ok(y2,m2,d2))
        v.push_back(node(y2,m2,d2));
                               //讨论 d/m/y 的情况
    int y3=1900+d,m3=m,d3=y;
    if(ok(y3,m3,d3))
        v.push_back(node(y3,m3,d3));
    y3=2000+d;
    if(ok(y3,m3,d3))
        v.push_back(node(y3,m3,d3));

    sort(v.begin(),v.end());//排序,从早到晚输出
    v.erase(unique(begin(v), end(v)), end(v));//去除重复项
    for(vector<node>::iterator it=v.begin();it!=v.end();it++)
        printf("%04d-%02d-%02d\n",(*it).y,(*it).m,(*it).d);
    //cout<<y<<" "<<m<<" "<<d;
    //cout<<ok(2013,2,28);
    return 0;
}


太难了!呜呜呜
看完觉得有用点个赞吧
在这里插入图片描述

发布了14 篇原创文章 · 获赞 3 · 访问量 539

猜你喜欢

转载自blog.csdn.net/qq_44577309/article/details/104394233