在歌唱比赛的舞台上,公平的评分系统是保证比赛公正的关键。本文将带你用C++实现一个专业的歌唱比赛评分系统,掌握数组处理、排序算法与浮点数精度的综合应用!

问题背景与核心挑战

题目描述

n名同学参加歌唱比赛,接受m名评委的评分。每位同学的最终得分计算规则为:

  • 去掉一个最高分
  • 去掉一个最低分
  • 剩余m-2个评分的平均数
  • 需要找出所有同学中的最高分

数据规模

  • n ≤ 100(同学数量)
  • m ≤ 20(评委数量)
  • 评分范围:0-10分

关键难点分析

  1. 多维度数据处理:同时处理n个同学的m个评分
  2. 排序算法应用:快速找出最高分和最低分
  3. 浮点数精度:确保平均值计算和输出格式的准确性
  4. 最值筛选:从所有同学中找出最高分

算法思路解析

核心算法设计

// 计算单个同学的得分
double calculateScore(vector<int>& scores) {
    sort(scores.begin(), scores.end());
    int sum = accumulate(scores.begin() + 1, scores.end() - 1, 0);
    return (double)sum / (scores.size() - 2);
}

算法流程

1. 读取n, m
2. 对于每个同学:
   - 读取m个评分
   - 排序评分数组
   - 去掉首尾,计算中间部分平均值
3. 追踪所有同学中的最高分
4. 输出最高分,保留两位小数

C++完整实现

#include <iostream>
#include <vector>
#include <algorithm>
#include <iomanip>
#include <numeric>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    
    double maxScore = 0.0;
    
    // 处理每个同学的评分
    for (int i = 0; i < n; i++) {
        vector<int> scores(m);
        
        // 读取当前同学的m个评分
        for (int j = 0; j < m; j++) {
            cin >> scores[j];
        }
        
        // 排序评分(升序)
        sort(scores.begin(), scores.end());
        
        // 去掉最高分和最低分,计算剩余评分的和
        int sum = 0;
        for (int j = 1; j < m - 1; j++) {
            sum += scores[j];
        }
        
        // 计算平均分
        double average = (double)sum / (m - 2);
        
        // 更新最高分
        if (average > maxScore) {
            maxScore = average;
        }
    }
    
    // 输出结果,保留两位小数
    cout << fixed << setprecision(2) << maxScore << endl;
    
    return 0;
}

关键知识点深度解析

1. 排序算法应用(⭐⭐⭐⭐⭐)

sort(scores.begin(), scores.end());
  • 算法选择:使用快速排序,时间复杂度O(m log m)
  • 排序目的:便于快速访问最小值和最大值
  • 性能分析:m≤20,排序开销可忽略不计

2. 子数组求和技巧(⭐⭐⭐⭐)

for (int j = 1; j < m - 1; j++) {
    sum += scores[j];
}
  • 边界处理:索引从1到m-2,排除首尾元素
  • 效率优化:避免创建新数组,直接遍历原数组
  • 内存友好:零额外内存分配

3. 浮点数精度控制(⭐⭐⭐⭐⭐)

cout << fixed << setprecision(2) << maxScore;
  • 格式固定fixed确保小数位固定显示
  • 精度设置setprecision(2)控制两位小数
  • 四舍五入:自动处理舍入规则

算法精妙之处

数学模型的优雅

将复杂的评分规则转化为简单的数学运算:

  • 排序预处理:通过排序快速定位极值
  • 区间求和:计算中间部分的算术平均
  • 最值追踪:实时更新全局最大值

时间复杂度分析

  • 单同学处理:O(m log m + m) ≈ O(m log m)
  • 总体复杂度:O(n × m log m)
  • 实际性能:100 × 20 × log₂20 ≈ 100 × 20 × 4.3 ≈ 8600次操作

测试用例验证

题目样例验证

输入:
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

计算过程(以第一个同学为例):
原始评分:[4,7,2,6,10,7]
排序后:[2,4,6,7,7,10]
去掉首尾:[4,6,7,7]
求和:4+6+7+7=24
平均:24/4=6.00

输出:6.00(符合样例)

边界情况测试

测试场景 输入特征 验证要点
最小规模 n=1, m=3 基础功能验证
最大规模 n=100, m=20 性能压力测试
相同评分 所有评分相同 排序稳定性
极端评分 包含0和10分 边界值处理

常见错误与解决方案

错误1:整数除法问题

// 错误:整数除法导致精度丢失
double average = sum / (m - 2); // 结果被截断为整数

解决:使用强制类型转换(double)sum / (m - 2)

错误2:排序边界错误

// 错误:错误的索引范围
for (int j = 0; j < m - 2; j++) { // 应该从1开始
    sum += scores[j];
}

解决:正确理解排序后的索引对应关系

错误3:初始化问题

// 错误:maxScore初始值过小
double maxScore = 0; // 如果所有分数为负则出错

解决:初始化为-1.0或使用第一个同学的分数

算法优化进阶

使用标准库算法优化

// 使用accumulate计算和
int sum = accumulate(scores.begin() + 1, scores.end() - 1, 0);

// 使用max_element找最大值
maxScore = max(maxScore, average);

内存优化版

// 不使用vector,用数组存储
int scores[20];
for (int j = 0; j < m; j++) {
    cin >> scores[j];
}
sort(scores, scores + m);

流式处理版

// 边读边处理,不存储所有数据
double currentMax = -1.0;
for (int i = 0; i < n; i++) {
    // 直接处理当前同学数据
}

实际应用拓展

1. 竞赛评分系统

  • 体育比赛:体操、跳水等项目的评分计算
  • 学术竞赛:论文评审、项目答辩评分
  • 艺术比赛:音乐、舞蹈等艺术类评分

2. 数据清洗工具

  • 异常值检测:识别并排除数据中的极端值
  • 数据标准化:多种评分体系的统一处理
  • 质量评估:多维度评价的综合计算

3. 商业应用系统

  • 产品评价:电商平台的产品评分计算
  • 员工考核:KPI评分中的极值排除
  • 服务评价:客户满意度评分处理

竞赛技巧总结

输入处理模板

int n, m;
cin >> n >> m;
for (int i = 0; i < n; i++) {
    vector<int> scores(m);
    for (int j = 0; j < m; j++) {
        cin >> scores[j];
    }
    // 处理逻辑
}

调试输出技巧

#ifdef DEBUG
    cout << "同学" << i+1 << "的评分: ";
    for (int score : scores) cout << score << " ";
    cout << "-> 最终得分: " << average << endl;
#endif

性能测试用例

// 测试最大数据量
输入:100 20(全部填充随机数据)
验证:快速正确计算

// 测试边界值
输入:1 3\n0 5 10
验证:正确计算(0+5+10-0-10)/1=5.00

总结与提升

通过这道歌唱比赛评分题目,我们掌握了:

核心技术要点

  1. 数组排序:快速定位数据中的极值
  2. 子集处理:高效计算部分数据的统计量
  3. 浮点精度:确保计算结果的准确性

编程思维提升

"在数据处理中,理解业务规则并转化为高效算法是关键能力。这道题教会我们:需求分析 → 数学建模 → 算法选择 → 代码实现的完整问题解决流程。"

关键收获

  • 排序算法在实际问题中的应用
  • 浮点数精度控制的必要性
  • 最值追踪的通用模式

 🔥 关注我,解锁CSP-J/S竞赛全攻略 🔥

(每日更新高频考点 + 精选真题解析,助你轻松备赛!)
👇 点击关注立即提升竞赛战力 👇
[https://blog.csdn.net/stillwatersss]


📚 专栏亮点抢先看
  1. 高频考点突破

    • 每日一题:精选洛谷/LeetCode CSP-J/S经典真题,附详细题解与时间复杂度优化技巧
    • 考点拆解:动态规划、图论、字符串算法等核心专题深度剖析,直击竞赛命题规律
    • 实战模板:限时领取《C++竞赛模板大全》👉 关注后私信回复“模板”获取
  2. 备赛效率翻倍技巧

    • 从O(n²)到O(n):独家算法优化套路,解决TLE超时问题
    • 考场避坑指南:常见失分点分析 + 数据边界处理技巧
    • 互动答疑:评论区留言题目编号,优先解析你的个性化难题
  3. 独家福利🌟

    • 粉丝专享:高价值文章设为 “仅粉丝可见”(如《CSP-J/S近5年考点分布与预测》)
    • 资料包:关注后私信 “资料” 领取 竞赛真题库+调试代码工具包

💡 为什么值得关注?

数据驱动:内容基于CSP-J/S真题大数据,命中率超80%
即学即用:每篇附可运行代码(代码通过洛谷测评)与测试用例
垂直领域:专注竞赛辅导,拒绝泛技术水文,直击备赛痛点

📢 今日关注福利:前100名新粉丝回复【进阶】赠送《洛谷青铜~黄金段位进阶题库》📘
🔥 行动提示:点击主页 → 专栏 → 开启订阅更新,系统自动推送最新解析!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐