【深基7.例4】歌唱比赛

每名选手去掉一个最高分和一个最低分后求平均,用 max 维护最高得分。

OJ: luogu

题目 ID: P5738

难度:入门

标签:模拟数组python

日期: 2026-07-15 21:08

题意

n 名选手,每人有 m 个评委打分。每名选手去掉一个最高分和一个最低分,剩下分数的平均值作为最终得分。求所有选手中的最高得分,保留两位小数。

思路

对每名选手的分数 scores

text
有效总分 = sum(scores) - max(scores) - min(scores)
平均分 = 有效总分 / (m - 2)

用变量 best 维护目前最高的平均分。

这题是数组聚合函数练习,不创建 brute.py

Python 知识

  • /home/rainboy/mycode/hugo-blog/content/program_language/python/input_output_and_strings.md:按行读取每名选手的分数。
  • /home/rainboy/mycode/hugo-blog/content/program_language/python/generator_expression.mdsummaxmin 是常用聚合函数。
  • best = max(best, average) 用于维护最大值。
  • f"{best:.2f}" 输出两位小数。

代码

python
n, m = map(int, input().split())
best = 0.0

for _ in range(n):
    scores = list(map(int, input().split()))
    total = sum(scores) - max(scores) - min(scores)
    average = total / (m - 2)
    best = max(best, average)

print(f"{best:.2f}")
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-07-27 00:00
 * update_at: 2026-07-27 00:00
 */

#include <bits/stdc++.h>
using namespace std;

int n, m;

int main() {
    cin >> n >> m;
    double best = 0; // 最高平均分
    for (int i = 1; i <= n; i++) {
        int sum = 0, maxs = 0, mins = 105;
        for (int j = 1; j <= m; j++) {
            int x;
            cin >> x;
            sum += x;
            if (x > maxs) maxs = x;
            if (x < mins) mins = x;
        }
        // 去掉最高分和最低分后的平均分
        double avg = 1.0 * (sum - maxs - mins) / (m - 2);
        if (avg > best) best = avg;
    }
    printf("%.2f", best);
    return 0;
}

Guide 风格代码

cppbook《C++ 快速入门》教学风格的写法(std:: 前缀、i += 1 循环、0 起始下标):

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-08-14 14:57
 * update_at: 2026-08-14 14:57
 */
#include <iomanip>
#include <iostream>

double average_score(const double score[], int count) {
    // 去掉一个最高分和一个最低分后求平均
    double total = 0.0;
    double max_score = score[0];
    double min_score = score[0];
    for (int i = 0; i < count; i += 1) {
        total += score[i];
        if (score[i] > max_score) {
            max_score = score[i];
        }
        if (score[i] < min_score) {
            min_score = score[i];
        }
    }
    total = total - max_score - min_score;
    // 剩下 count - 2 个有效评分
    return total / (count - 2);
}

int main() {
    int player_count, judge_count;
    std::cin >> player_count >> judge_count;

    const int max_judges = 20;
    double scores[max_judges];

    double best = 0.0;
    for (int player = 0; player < player_count; player += 1) {
        for (int judge = 0; judge < judge_count; judge += 1) {
            std::cin >> scores[judge];
        }
        double average = average_score(scores, judge_count);
        // 只保留最高的平均分
        if (average > best) {
            best = average;
        }
    }

    std::cout << std::fixed << std::setprecision(2) << best << '\n';
    return 0;
}

Pythonic 写法

生成器求最高均分:

python
n, m = map(int, input().split())
best = max(
    (sum(scores) - max(scores) - min(scores)) / (m - 2)
    for scores in (list(map(int, input().split())) for _ in range(n))
)
print(f'{best:.2f}')

复杂度

共有 n 名选手,每名选手 m 个分数,时间复杂度是 O(nm)O(nm),空间复杂度是 O(m)O(m)

总结

去掉最高最低分时,不一定要排序。只需要总和、最大值和最小值,就能算出有效平均分。