top1编程
← 返回题目
题解

生日

1 条题解

  • 0
    @ 2026-8-6 1:50:12

    P4618 生日(基础)

    解题思路

    按年龄从大到小给同学排队,可以巧妙地转化成"按出生日期从早到晚排序"。分四步做。

    第一步,把问题转化一下。 年龄大的人,出生日期一定更早。所以"年龄从大到小"就等价于"出生日期从早到晚"。比如 2013 年出生的小朋友一定比 2012 年出生的小,这个道理大家都懂。出生日期有年、月、日三部分,比较时先比年份,年份相同比月份,年月都相同再比日期。

    第二步,用结构体保存信息。 结构体 Birthday 保存姓名、出生年、出生月、出生日。姓名是字符串,用字符数组存。

    第三步,写比较函数一层层比。 比较函数里按"年、月、日"的优先级判断:年份不同就按年份小的排前面;年份相同看月份,月份小的靠前;年月都相同看日期,日期小的靠前。排出来的顺序正好是出生日期从早到晚,也就是年龄从大到小。

    第四步,用例子验证并输出。 用生活经验来想:同样是 2012 年出生,8 月的小朋友比 9 月的大;都是 9 月,26 号出生的又比 29 号的大。样例里 lili(2012 年 8 月 26 日)最大排第一,qiqi(2012 年 9 月 26 日)第二,yaya(2012 年 9 月 29 日)最后。题目保证年份在 1990 到 2022 之间、日期真实存在,也保证没有两个同学生日相同,所以直接读入、排序、输出姓名即可。

    **回顾总结。**比较日期就像查字典,先看年、再看月、最后看日,一层一层来,绝不跨层比较。把"年龄从大到小"翻译成"日期从小到大",问题就变成最常见的结构体排序。注意样例里三个同学同年,所以比月份和日期就够用了。

    参考代码

    // 生日:按出生日期从早到晚排序(年龄从大到小),输出姓名
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    // 保存一名同学的姓名和出生日期
    struct Birthday {
        char name[30];   // 姓名
        int year;        // 出生年
        int month;       // 出生月
        int day;         // 出生日
    };
    
    // 自定义比较函数:出生日期早的(年龄大的)排前面
    bool cmp(const Birthday &a, const Birthday &b) {
        if (a.year != b.year) return a.year < b.year;
        if (a.month != b.month) return a.month < b.month;
        return a.day < b.day;
    }
    
    int main() {
        int n;
        Birthday stu[105];
        cin >> n;
        for (int i = 0; i < n; i++) {
            cin >> stu[i].name >> stu[i].year >> stu[i].month >> stu[i].day;
        }
        sort(stu, stu + n, cmp);   // 年龄大的(生日早的)在前
        for (int i = 0; i < n; i++) {
            cout << stu[i].name << endl;
        }
        return 0;
    }
    

    复杂度分析

    sort() 排序的时间复杂度是 O(n log n),n 是小组人数(1 < n < 100)。每个结构体存姓名和一个日期,空间复杂度是 O(n)。数据规模小,程序运行极快。

    • 1