题解:洛谷 P1104 生日
【题目来源】
洛谷:P1104 生日 - 洛谷(luogu.com.cn)
【题目描述】
cjf 君想调查学校 OI 组每个同学的生日,并按照年龄从大到小的顺序排序。但 cjf 君最近作业很多,没有时间,所以请你帮她排序。
【输入】
输入共有 \(n+1\) 行,
第 \(1\) 行为 OI 组总人数 \(n\);
第 \(2\) 行至第 \(n+1\) 行分别是每人的姓名 \(s\)、出生年 \(y\)、月 \(m\)、日 \(d\)。
【输出】
输出共有 \(n\) 行,
即 \(n\) 个生日从大到小同学的姓名。(如果有两个同学生日相同,输入靠后的同学先输出)
【输入样例】
3
Yangchu 1992 4 23
Qiujingya 1993 10 13
Luowen 1991 8 1
【输出样例】
Luowen
Yangchu
Qiujingya
【核心思想】
-
问题分析:给定 \(n\) 名学生的姓名和出生日期(年、月、日),要求按年龄从大到小排序(即出生日期越早越靠前)。如果两个学生生日完全相同,则输入靠后的学生排在前面。本质是一个多关键字排序问题,排序优先级为:年升序 → 月升序 → 日升序 → 输入顺序降序。
-
算法选择:
- 结构体 + 自定义比较函数:使用结构体存储姓名、年、月、日和输入顺序。利用
std::sort配合自定义比较函数,实现按年龄从大到小(即日期从小到大)排序,生日相同时按输入顺序降序。 - 复杂度:时间复杂度 \(O(n \log n)\),空间复杂度 \(O(n)\)。
- 结构体 + 自定义比较函数:使用结构体存储姓名、年、月、日和输入顺序。利用
-
关键步骤:
- 读入:读取 \(n\),然后对于每个学生 \(i\),读入姓名、年、月、日,记录
order = i(从 0 开始)。 - 排序:比较函数
cmp先按年、月、日升序比较,若完全相等则按order降序(即后输入的先输出)。 - 输出:按排序后的顺序输出姓名。
- 读入:读取 \(n\),然后对于每个学生 \(i\),读入姓名、年、月、日,记录
-
时间/空间复杂度:
- 时间复杂度:\(O(n \log n)\)。
- 空间复杂度:\(O(n)\)。
-
多关键字排序:
- 年龄与日期关系:年龄大 = 出生日期早(年小、月小、日小)。
- 稳定排序处理同生日:使用输入顺序作为第四关键字,并降序排列,以满足“输入靠后的先输出”。
- 适用场景:这类“按日期排序”问题,是结构体排序的典型应用。
【解题思路】

【算法标签】
普及- #其他排序
【代码详解】
#include <bits/stdc++.h> // 包含常用的头文件
using namespace std;
// 定义学生结构体,包含姓名、出生年、月、日以及输入顺序
struct student {
string name; // 学生姓名
int year, mon, day; // 出生日期:年、月、日
int order; // 输入顺序,用于处理同一天生日的学生
}ss[105]; // 定义一个最多可以存储105个学生的数组
// 自定义比较函数,用于排序
bool cmp(student s1, student s2)
{
// 1. 首先按出生年份从小到大排序
if (s1.year != s2.year) return s1.year < s2.year;
// 2. 如果年份相同,按月份从小到大排序
if (s1.mon != s2.mon) return s1.mon < s2.mon;
// 3. 如果月份相同,按日期从小到大排序
if (s1.day != s2.day) return s1.day < s2.day;
// 4. 如果日期也相同,按输入顺序从后往前排序(order大的排在前面)
return s1.order > s2.order;
}
int main()
{
int n; // n: 学生总数
cin >> n; // 输入学生总数
// 输入每个学生的姓名和出生日期,并记录输入顺序
for (int i=0; i<n; i++) {
cin >> ss[i].name >> ss[i].year >> ss[i].mon >> ss[i].day;
ss[i].order = i; // 记录输入顺序
}
// 对学生数组进行排序,排序规则由cmp函数决定
sort(ss, ss+n, cmp);
// 输出排序后的学生姓名
for (int i=0; i<n; i++) {
cout << ss[i].name << endl;
}
return 0; // 程序结束
}
【运行结果】
3
Yangchu 1992 4 23
Qiujingya 1993 10 13
Luowen 1991 8 1
Luowen
Yangchu
Qiujingya
浙公网安备 33010602011771号