把「总分降序、语文降序、学号升序」三段规则合成一个排序键 (-总分, -语文, 学号),一次排序取前 5 名。
OJ: roj
题目 ID: 1179
难度:入门
标签:排序模拟python
创建: 2026-09-29 22:29
更新: 2026-10-05 04:26
题目描述
6 + 90 67 80 / 87 66 91 / 78 89 91 / 88 99 77 / 67 89 64 / 78 89 98,输出 6 265 / 4 264 / 3 258 / 2 244 / 1 237。
思路
先算出每人总分
参考代码
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:29
# update_at: 2026-10-04 09:35
import sys
TOP = 5 # 只有前 5 名拿奖学金
SUBJECTS = 3 # 每人语文、数学、英语三门成绩
def rank_key(stu: tuple[int, int, int]) -> tuple[int, int, int]:
"""奖学金排序键:总分高者在前,同分看语文,再同学号小者在前。"""
idx, total, chinese = stu
return (-total, -chinese, idx)
def solve() -> None:
data = iter(map(int, sys.stdin.buffer.read().split()))
count = next(data) # 参评学生人数
# (学号, 总分, 语文),学号即输入行号,从 1 开始
students = [
(i + 1, sum(scores), scores[0])
for i in range(count)
if (scores := [next(data) for _ in range(SUBJECTS)])
]
# 排序键统一取负号,把"从大到小"折成"从小到大",学号本身就是升序
students.sort(key=rank_key)
print('\n'.join(f"{idx} {total}" for idx, total, _ in students[:TOP]))
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:26
* update_at: 2026-10-05 04:26
*/
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 305; // n < 300,多开几个下标防止越界
// 一个学生的排序所需信息
struct Student {
ll id; // 学号,即输入行号(从 1 开始)
ll total; // 语文 + 数学 + 英语
ll chinese; // 语文成绩,总分并列时用来比较
};
ll n;
Student stu[MAXN]; // stu[i] 表示学号为 i 的学生
// 题面规则:总分从高到低,总分相同看语文从高到低,再相同则学号小的在前。
bool cmp_student(const Student &a, const Student &b) {
if (a.total != b.total) return a.total > b.total;
if (a.chinese != b.chinese) return a.chinese > b.chinese;
return a.id < b.id;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
for (ll i = 1; i <= n; i++) {
ll chinese, math, english;
cin >> chinese >> math >> english;
stu[i].id = i;
stu[i].total = chinese + math + english;
stu[i].chinese = chinese;
}
sort(stu + 1, stu + n + 1, cmp_student);
// 按名次输出前 5 名的学号与总分
ll top = (n < 5 ? n : 5);
for (ll i = 1; i <= top; i++) {
cout << stu[i].id << " " << stu[i].total << "\n";
}
return 0;
}