把三条排队规则压成一个排序键(是否非老年人、老年人负年龄、登记序号),字典序比较一次排序同时完成分组、组内排序与平局裁决。
OJ: roj
题目 ID: 1183
难度:入门
标签:入门排序python
创建: 2026-09-29 22:27
更新: 2026-10-05 04:34
题目描述
病人登记看病,按三条规则排出看病顺序:年龄 5 / 021075 40 / 004003 15 / 010158 67 / 021033 75 / 102012 30,期望输出 021033 / 010158 / 021075 / 004003 / 102012。
思路
把三条规则压成一个排序键 (age < 60, 老年人 ? -age : 0, 登记序号),按它排一次序再依次输出:第 1 位让老年人排前面,第 2 位让老年人年龄大的在前(非老年人固定为 0,年龄不参与),第 3 位由登记序号兜底裁决平局。ID 含前导零,必须按字符串处理。
参考代码
Python 版:
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-09-29 22:28
# update_at: 2026-09-29 22:28
import sys
ELDERLY_AGE = 60 # 老年人门槛:年龄 >= 60 者优先看病
def visit_key(person: tuple[bytes, int, int]) -> tuple[bool, int, int]:
"""看病顺序键:老年人优先,老年人按年龄从大到小,登记序号兜底保持先来后到。"""
_pid, age, idx = person
# 非老年人的年龄不参与排序,统一记 0;同键由登记序号按输入先后打破平局
return (age < ELDERLY_AGE, -age if age >= ELDERLY_AGE else 0, idx)
def solve() -> None:
data = iter(sys.stdin.buffer.read().split())
count = next(data) # 病人个数
# (ID, 年龄, 登记序号),登记序号即输入行的先后,也是同组内的平局裁决
people: list[tuple[bytes, int, int]] = [
(pid, int(age), i) for i, (pid, age) in enumerate(zip(data, data))
]
people.sort(key=visit_key)
print(b'\n'.join(pid for pid, _, _ in people).decode())
if __name__ == "__main__":
solve()C++ 版(同一算法):
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-05 04:33
* update_at: 2026-10-05 04:33
*/
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
typedef long long ll;
// n < 100,开 105 足够。
const ll MAXN = 105;
// 老年人门槛:年龄 >= 60 者优先看病。
const ll ELDERLY_AGE = 60;
// 病人:ID 含前导零,必须用字符串保存,不能转成整数。
struct Patient {
string id;
ll age;
ll idx; // 登记序号,即输入行的先后,用来打破同组内的平局
};
Patient pat[MAXN]; // pat[i] 表示第 i 个登记的病人
ll n;
// 排队规则:老年人优先;老年人按年龄从大到小;其余情况一律按登记先后。
bool cmp_by_visit_order(const Patient &a, const Patient &b) {
ll group_a = (a.age >= ELDERLY_AGE) ? 0 : 1; // 老年人取 0,排前面
ll group_b = (b.age >= ELDERLY_AGE) ? 0 : 1;
if (group_a != group_b) return group_a < group_b;
// 同组内:老年人比年龄(大的在前),非老年人不比年龄(年龄一律看成 0)
ll key_a = (a.age >= ELDERLY_AGE) ? -a.age : 0;
ll key_b = (b.age >= ELDERLY_AGE) ? -b.age : 0;
if (key_a != key_b) return key_a < key_b;
return a.idx < b.idx; // 平局由登记序号裁决
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
for (ll i = 1; i <= n; i++) {
cin >> pat[i].id >> pat[i].age;
pat[i].idx = i;
}
sort(pat + 1, pat + n + 1, cmp_by_visit_order);
for (ll i = 1; i <= n; i++) {
cout << pat[i].id << "\n";
}
return 0;
}