题解:洛谷 P5726 打分
【题目来源】
【题目描述】
现在有 \(n(n\le 1000)\) 位评委给选手打分,分值从 \(0\) 到 \(10\)。需要去掉一个最高分,去掉一个最低分(如果有多个最高或者最低分,也只需要去掉一个),剩下的评分的平均数就是这位选手的得分。现在输入评委人数和他们的打分,请输出选手的最后得分,精确到 \(2\) 位小数。
【输入】
第一行输入一个正整数 \(n\),表示有 \(n\) 个评委。
第二行输入 \(n\) 个正整数,第 \(i\) 个正整数表示第 \(i\) 个评委打出的分值。
【输出】
输出一行一个两位小数,表示选手的最后得分。
【输入样例】
5 9 5 6 8 9
【输出样例】
7.67
【核心思想】
-
问题分析:有 \(n\) 个评委打分(分值 \(0 \sim 10\)),需要去掉一个最高分和一个最低分后,计算剩余分数的平均值。即使有多个最高或最低分,也只需各去掉一个。本质是在给定的一组数据中,剔除最大值和最小值各一个,然后求平均。
-
算法选择:
- 一次遍历 + 维护最值:在读取数据的同时,累加总和并记录最大值和最小值。最后从总和中减去一个最大值和一个最小值,再除以 \(n-2\) 即可得到平均值。无需排序,时间复杂度 \(O(n)\),空间复杂度 \(O(1)\)。
-
关键步骤:
- 读入与初始化:读取 \(n\),再读取第一个分数
t,将max、min和sum初始化为t。 - 遍历剩余分数:对于 \(i = 2\) 到 \(n\),读入每个分数
t,累加到sum,并更新max和min。 - 计算平均值:去掉一个最高分和一个最低分后的平均值为
(sum - max - min) / (n - 2),注意使用浮点数除法。 - 输出:按两位小数格式输出结果(如
printf("%.2f", ans))。
- 读入与初始化:读取 \(n\),再读取第一个分数
-
时间/空间复杂度:
- 时间复杂度:\(O(n)\),其中 \(n \le 1000\),完全可行。
- 空间复杂度:\(O(1)\),只使用了常数个变量。
-
模拟与数学:
- 最值维护:通过一次遍历同时记录最大值和最小值,避免了排序的 \(O(n \log n)\) 开销。
- 整数与浮点转换:在计算平均值时,需将分子转为浮点数(如乘以
1.0),以确保得到小数结果。 - 边界情况:\(n \ge 3\)(隐含),因为需要去掉两个分数后仍有剩余分数计算平均值。
- 适用场景:适用于需要剔除数据集中极值后求平均的场景,如评委打分、统计异常值剔除等。
【算法标签】
普及- #模拟
【代码详解】
#include <bits/stdc++.h> // 包含标准库头文件(万能头文件)
using namespace std; // 使用标准命名空间
/**
* 主函数 - 程序入口
* @return 程序执行状态码(0表示成功)
*/
int main()
{
int n; // 定义变量:数据个数
int t; // 定义变量:临时存储输入的数据
int max, min; // 定义变量:最大值和最小值
int sum = 0; // 定义变量:数据总和,初始化为0
cin >> n; // 输入数据个数
cin >> t; // 输入第一个数据
// 初始化最大值、最小值和总和
max = t;
min = t;
sum += t;
// 遍历剩余的数据
for (int i = 1; i < n; i++)
{
cin >> t; // 输入当前数据
sum += t; // 累加到总和
// 更新最大值
if (max < t)
max = t;
// 更新最小值
if (min > t)
min = t;
}
// 计算去掉一个最高分和一个最低分后的平均值
double ans = 1.0 * (sum - max - min) / (n - 2);
// 输出结果,保留两位小数
printf("%.2f", ans);
return 0; // 程序正常结束
}
【运行结果】
5
9 5 6 8 9
7.67
浙公网安备 33010602011771号