传送门:P1104 生日

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


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

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

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

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

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

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

  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;
}
最后修改:2025 年 08 月 10 日
如果觉得我的文章对你有用,请随意赞赏