PAT单位排行
1. 题目地址
https://www.acwing.com/problem/content/1636/
2. 题目解析
本题需要知道:多关键字排序、构造函数、unordered_map的知识。
3. 题解
我们需要用结构体来存储学校的三个信息:
1. 名称(用于日后输出)
2. 加权分
3. 人数
在输入的时候,我们可以声明map,来将学校的名字和代表学校的结构体关联起来,边接收边处理。
在处理的过程中,有时需要除以1.5,1.5包含因子3。因此,可能会有除不尽的情况。例如:总分 / 1.5 = 123.9999999。实际为124。如果直接截断,则为123,这是精度不正确导致的错误。
因此,我们可以加上一个小的误差。这里的经验值为1e-8。这样的话,再进行截断,就不会有精度的问题了。
处理完成后,我们再将结构体放在vector数组中。再按照多关键字进行排序。排序之后,注意处理排名的问题就可以了。
注意:由于本题关于学校的名称是不区分大小写的。因此,在接收数据时,统一转换成小写即可。
4. 代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;
struct School{
double sum;
int cnt;
string name;
//定义构造函数
School(): sum(0),cnt(0){}
//重载小于号,进行多关键字排序
bool operator<(School &s) const{
if(sum != s.sum){
return sum > s.sum;
}
if(cnt != s.cnt){
return cnt < s.cnt;
}
return name < s.name;
}
};
unordered_map<string,School> h;
vector<School> schools;
string to_lower(string str){
string result = "";
for(int i = 0; i < str.size(); i ++){
if(str[i] >= 'A' && str[i] <= 'Z'){
result += str[i] + 32;
}else{
result += str[i];
}
}
return result;
}
int main(){
int n;
scanf("%d",&n);
for(int i = 0; i < n; i ++){
string id,sch;
double score;
cin >> id >> score >> sch;
//计算加权总分
if(id[0] == 'B'){
score /= 1.5;
}else if(id[0] == 'T'){
score *= 1.5;
}
//将学校名称,统一转换成小写
sch = to_lower(sch);
h[sch].sum += score;
h[sch].cnt++;
h[sch].name = sch;
}
for(auto item : h){
//加上一个非常小的数,解决精度问题
item.second.sum = (int)(item.second.sum + 1e-8);
//将学校(结构体)放在vector数组中
schools.push_back(item.second);
}
//将学校按照多关键字排序
sort(schools.begin(),schools.end());
printf("%ld\n",schools.size());
int order = 1;
for(int i = 0; i < schools.size(); i ++){
if(i != 0 && schools[i].sum != schools[i-1].sum){
order = i + 1;
}
//输出相关信息
printf("%d %s %d %d\n",order,schools[i].name.c_str(),(int)schools[i].sum,schools[i].cnt);
}
return 0;
}