P1104 题解

· · 题解

传送门:P1104 生日

更佳的阅读体验:洛谷 P1104 题解

简要题意:给定 n 位同学的姓名和生日,要求对这些同学按年龄从大到小排序。

看到这么多信息,我们应该可以想到,使用结构体来维护每个同学的信息。

但题目要求我们,如果生日完全相同时,后输入的同学先输出。因此除了题目给出的 s,y,m,d 四个变量,我们还需要在结构体中维护一个变量 num,用于存储该同学是第几个被输入的。

题目要求我们对每个同学按照年龄为关键字排序,但我们发现,对每个同学计算年龄是很复杂的。因此我们考虑转换思路。

可以想到,如果一个同学 a 比另一个同学 b 出生得更早,那么同学 a 一定比同学 b 更大。

接下来就可以考虑定义排序规则了。我们发现,对于两个同学 abab 先输出,当且仅当:

  1. y_a \neq y_b,则 y_a < y_b 时。
  2. 否则,若 m_a \neq m_b,有 m_a < m_b 时。
  3. 否则,若 d_a \neq d_b,则 d_a < d_b 时。
  4. 否则,有 num_a > num_b 时。

按上述规则排序即可。

对于排序规则,下文代码中使用了重载 < 运算符,它等价于编写一个自定义排序函数。编写自定义排序函数的做法将以注释的形式给出。

#include <iostream>
#include <algorithm>
using namespace std;

const int N = 110;
int n;
struct student {
    string s;
    int y, m, d, num;
    bool operator<(const student x) const {
        if (y != x.y) return y < x.y;
        if (m != x.m) return m < x.m;
        if (d != x.d) return d < x.d;
        return num > x.num;
    }
} a[N];

/* bool cmp(student a, student b) {
    if (a.y != b.y) return a.y < b.y;
    if (a.m != b.m) return a.m < b.m;
    if (a.d != b.d) return a.d < b.d;
    return a.num > b.num;
} */

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cin >> n;
    for (int i = 1; i <= n; ++i)
        cin >> a[i].s >> a[i].y >> a[i].m >> a[i].d, a[i].num = i;
    sort(a + 1, a + n + 1);
    // sort(a + 1, a + n + 1, cmp);
    for (int i = 1; i <= n; ++i) cout << a[i].s << '\n';
    return 0;
}