歌唱比赛评分系统:C++实现高效评分计算与最值筛选(洛谷P5738)
·

在歌唱比赛的舞台上,公平的评分系统是保证比赛公正的关键。本文将带你用C++实现一个专业的歌唱比赛评分系统,掌握数组处理、排序算法与浮点数精度的综合应用!
问题背景与核心挑战
题目描述
n名同学参加歌唱比赛,接受m名评委的评分。每位同学的最终得分计算规则为:
- 去掉一个最高分
- 去掉一个最低分
- 剩余m-2个评分的平均数
- 需要找出所有同学中的最高分
数据规模
- n ≤ 100(同学数量)
- m ≤ 20(评委数量)
- 评分范围:0-10分
关键难点分析
- 多维度数据处理:同时处理n个同学的m个评分
- 排序算法应用:快速找出最高分和最低分
- 浮点数精度:确保平均值计算和输出格式的准确性
- 最值筛选:从所有同学中找出最高分
算法思路解析
核心算法设计
// 计算单个同学的得分
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
总结与提升
通过这道歌唱比赛评分题目,我们掌握了:
核心技术要点
- 数组排序:快速定位数据中的极值
- 子集处理:高效计算部分数据的统计量
- 浮点精度:确保计算结果的准确性
编程思维提升
"在数据处理中,理解业务规则并转化为高效算法是关键能力。这道题教会我们:需求分析 → 数学建模 → 算法选择 → 代码实现的完整问题解决流程。"
关键收获:
- 排序算法在实际问题中的应用
- 浮点数精度控制的必要性
- 最值追踪的通用模式
🔥 关注我,解锁CSP-J/S竞赛全攻略 🔥
(每日更新高频考点 + 精选真题解析,助你轻松备赛!)
👇 点击关注 → 立即提升竞赛战力 👇
[https://blog.csdn.net/stillwatersss]
📚 专栏亮点抢先看
-
高频考点突破
- 每日一题:精选洛谷/LeetCode CSP-J/S经典真题,附详细题解与时间复杂度优化技巧
- 考点拆解:动态规划、图论、字符串算法等核心专题深度剖析,直击竞赛命题规律
- 实战模板:限时领取《C++竞赛模板大全》👉 关注后私信回复“模板”获取
-
备赛效率翻倍技巧
- 从O(n²)到O(n):独家算法优化套路,解决TLE超时问题
- 考场避坑指南:常见失分点分析 + 数据边界处理技巧
- 互动答疑:评论区留言题目编号,优先解析你的个性化难题
-
独家福利🌟
- 粉丝专享:高价值文章设为 “仅粉丝可见”(如《CSP-J/S近5年考点分布与预测》)
- 资料包:关注后私信 “资料” 领取 竞赛真题库+调试代码工具包
💡 为什么值得关注?
✅ 数据驱动:内容基于CSP-J/S真题大数据,命中率超80%
✅ 即学即用:每篇附可运行代码(代码通过洛谷测评)与测试用例
✅ 垂直领域:专注竞赛辅导,拒绝泛技术水文,直击备赛痛点
📢 今日关注福利:前100名新粉丝回复【进阶】赠送《洛谷青铜~黄金段位进阶题库》📘
🔥 行动提示:点击主页 → 专栏 → 开启订阅更新,系统自动推送最新解析!
更多推荐
所有评论(0)