[NOIP2007-普及] 奖学金

GitHub跳转原题关系图返回列表

读入三科成绩算总分,按总分、语文、学号排序后输出前 5 名。

OJ: roj

题目 ID: 3552

难度:入门

标签:入门条件判断python

创建: 2026-10-02 07:06

更新: 2026-10-06 13:43

题目描述

nn 名学生每人有语文、数学、英语三科成绩,学号即输入顺序 1∼n1 \sim n。按总分从高到低排序;总分相同则语文高者靠前;仍相同则学号小者靠前。输出前 55 名的学号与总分。

思路

读入时计算总分并记录语文成绩和学号,用结构体数组按规则排序后输出前 55 名即可。

参考代码

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-10-02 07:06
# update_at: 2026-10-02 07:45

import sys


def money(avg: float, ev: float, cadre: str, west: str, papers: int) -> int:
    """五项奖学金全部命中的金额之和:bool 乘金额,命中加钱、未命中加 0。"""
    return (
        8000 * (avg > 80 and papers >= 1)  # 均分 >80 且有论文
        + 4000 * (avg > 85 and ev > 80)  # 均分 >85 且评议 >80
        + 2000 * (avg > 90)  # 均分 >90
        + 1000 * (avg > 85 and west == "Y")  # 均分 >85 的西部学生
        + 850 * (ev > 80 and cadre == "Y")  # 评议 >80 的学生干部
    )


def solve() -> None:
    lines = sys.stdin.read().splitlines()
    n = int(lines[0])  # 学生人数
    top_name, top_money, total = "", -1, 0

    for line in lines[1 : n + 1]:
        name, avg, ev, cadre, west, papers = line.split()
        amount = money(float(avg), float(ev), cadre, west, int(papers))
        total += amount
        if amount > top_money:  # 严格大于:并列时保留最先出现的学生
            top_name, top_money = name, amount

    print(f"{top_name}\n{top_money}\n{total}")


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-06 13:43
 * update_at: 2026-10-06 13:45
 */
#include <cstdio>
#include <algorithm>

using namespace std;

typedef long long ll;

const int MAXN = 305; // 学生人数上限

struct Student {
    int id;      // 学号
    int total;   // 三科总分
    int chinese; // 语文成绩
} a[MAXN];

int n;

// 排序规则:总分降序,语文降序,学号升序
bool cmp(const Student &x, const Student &y) {
    if (x.total != y.total) return x.total > y.total;
    if (x.chinese != y.chinese) return x.chinese > y.chinese;
    return x.id < y.id;
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        int c, m, e;
        scanf("%d%d%d", &c, &m, &e);
        a[i].id = i;
        a[i].chinese = c;
        a[i].total = c + m + e;
    }
    sort(a + 1, a + n + 1, cmp);
    int k = n < 5 ? n : 5; // 输出前 5 名,不足 5 名则全部输出
    for (int i = 1; i <= k; i++) {
        printf("%d %d\n", a[i].id, a[i].total);
    }
    return 0;
}