题解:洛谷 P5738 歌唱比赛

【题目来源】

洛谷:P5738 【深基7.例4】歌唱比赛 - 洛谷

【题目描述】

\(n(n\le 100)\) 名同学参加歌唱比赛,并接受 \(m(m\le 20)\) 名评委的评分,评分范围是 \(0\)\(10\) 分。这名同学的得分就是这些评委给分中去掉一个最高分,去掉一个最低分,剩下 \(m-2\) 个评分的平均数。请问得分最高的同学分数是多少?评分保留 \(2\) 位小数。

【输入】

第一行两个整数 \(n,m\)

接下来 \(n\) 行,每行各 \(m\) 个整数,表示得分。

【输出】

输出分数最高的同学的分数,保留两位小数。

【输入样例】

7 6
4 7 2 6 10 7
0 5 0 10 3 10
2 6 8 4 3 6
6 3 6 7 5 8
5 9 3 3 8 1
5 9 9 3 2 0
5 8 0 4 1 10

【输出样例】

6.00

【核心思想】

  1. 问题分析:有 \(n\) 名同学参加歌唱比赛,每名同学有 \(m\) 个评委的评分(\(0 \sim 10\) 分)。每名同学的最终得分为去掉一个最高分和一个最低分后的平均分。需要求出所有同学中最高得分,并保留两位小数。本质是多组数据的最值统计与平均值计算问题,核心是每组数据需要去掉极值后求平均,然后取最大值。

  2. 算法选择

    • 逐组处理 + 动态维护:对每组 \(m\) 个评分,在输入过程中同时记录总和、最大值和最小值,输入完成后即可计算去掉极值后的平均值。这样无需存储所有评分,节省空间。
    • 复杂度:时间复杂度 \(O(n \times m)\),空间复杂度 \(O(1)\)
  3. 关键步骤

    • 读入:读取 \(n\)\(m\),初始化最高得分 max_score = -1
    • 处理每组数据
      • 读取第一个评分,初始化 summax_valmin_val
      • 继续读取剩余 \(m-1\) 个评分,更新 summax_valmin_val
      • 计算去掉最高分和最低分后的平均分:avg = (sum - max_val - min_val) / (m - 2)
      • avg > max_score,更新 max_score
    • 输出printf("%.2f", max_score)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n \times m)\)\(n \le 100, m \le 20\),非常快。
    • 空间复杂度:\(O(1)\),仅使用几个变量。
  5. 模拟与数据处理

    • 流式处理:在输入过程中直接计算,无需保存所有评分,这是处理大量数据时的常用技巧。
    • 极值维护:同时维护最大值和最小值,以便最后剔除。
    • 类型转换:计算平均值时,使用 1.0 * sum / (m - 2) 确保得到浮点数结果。
    • 适用场景:这类“多组数据统计”问题在竞赛中非常常见,练习了循环、条件判断和基本算术运算。

【算法标签】

普及- #模拟

【代码详解】

#include <bits/stdc++.h>  // 包含标准库头文件(万能头文件)
using namespace std;      // 使用标准命名空间

/**
 * 计算单个选手的最终得分(去掉最高分和最低分后的平均分)
 * @param m 评委人数
 * @return 选手的最终得分
 */
double judge(int m)
{
    int max, min, sum = 0, tmp;  // 定义变量:最高分、最低分、总分、临时分数
    double ans;                   // 定义变量:最终得分

    // 读取第一个评委的分数
    cin >> tmp;
    max = tmp;  // 初始化最高分
    min = tmp;  // 初始化最低分
    sum = tmp;  // 初始化总分

    // 读取剩余评委的分数
    for (int i = 2; i <= m; i++)
    {
        cin >> tmp;
        if (tmp > max) max = tmp;  // 更新最高分
        if (tmp < min) min = tmp;  // 更新最低分
        sum += tmp;                // 累加总分
    }

    // 计算去掉最高分和最低分后的总分
    sum -= max + min;
    // 计算平均分(保留两位小数)
    ans = 1.0 * sum / (m - 2);

    return ans;  // 返回最终得分
}

int main()
{
    int n, m;            // 定义变量:选手人数n,评委人数m
    double ans = -1;     // 定义变量:最高得分,初始为-1
    double tmp;          // 定义变量:临时存储得分

    cin >> n >> m;       // 输入选手人数和评委人数

    // 计算每位选手的得分,并找出最高分
    for (int i = 1; i <= n; i++)
    {
        tmp = judge(m);  // 计算当前选手得分
        if (ans < tmp)   // 更新最高得分
        {
            ans = tmp;
        }
    }

    // 输出最高得分,保留两位小数
    printf("%.2f", ans);

    return 0;            // 程序正常结束
}

【运行结果】

7 6
4 7 2 6 10 7
0 5 0 10 3 10
2 6 8 4 3 6
6 3 6 7 5 8
5 9 3 3 8 1
5 9 9 3 2 0
5 8 0 4 1 10
6.00
posted @ 2026-09-01 09:25  团爸讲算法  阅读(15)  评论(0)    收藏  举报