每次 PAT 考试结束后,考试中心都会发布一个考生单位排行榜。本题就请你实现这个功能。
输入格式:
输入第一行给出一个正整数 N(≤105),即考生人数。随后 N 行,每行按下列格式给出一个考生的信息:
准考证号 得分 学校
其中准考证号
是由 6 个字符组成的字符串,其首字母表示考试的级别:B
代表乙级,A
代表甲级,T
代表顶级;得分
是 [0, 100] 区间内的整数;学校
是由不超过 6 个英文字母组成的单位码(大小写无关)。注意:题目保证每个考生的准考证号是不同的。
输出格式:
首先在一行中输出单位个数。随后按以下格式非降序输出单位的排行榜:
排名 学校 加权总分 考生人数
其中排名
是该单位的排名(从 1 开始);学校
是全部按小写字母输出的单位码;加权总分
定义为乙级总分/1.5 + 甲级总分 + 顶级总分*1.5
的整数部分;考生人数
是该属于单位的考生的总人数。
学校首先按加权总分排行。如有并列,则应对应相同的排名,并按考生人数升序输出。如果仍然并列,则按单位码的字典序输出
思路分析:1.设计两个结构体,一个结构体存学生信息,另一个存学校的信息。
2.转化学校的大小写,用map去映射,相同的学校分数按类型加到一起。
易错点分析:最后一个测试点,一定要把分数设计成小数,最后是取整数不是四舍五入。整体来说PAT后面的大题基本都要用C++去写,C++中的函数比较方便,用C语言写会比较费劲。
#include<algorithm>
#include<string.h>
#include<iostream>
#include<map>
using namespace std;
typedef struct School
{
string school;
double score;
int num;
}School;
bool cmp(School s1,School s2)
{
int soc1 = s1.score,soc2 = s2.score;
if(soc1 != soc2) //需要转化成int类型再进行比较
return soc1 > soc2;
else if(s2.num != s1.num)
return s1.num < s2.num;
else
return s1.school< s2.school;
}
School sch[100005] = {};
int main()
{
int n = 0;
cin >> n;
string id;
double score; //分数要定义成浮点型
string school;
map<string,int> m; //值记录的就是学校的下标
int index = 0; //记录学校数量
for(int i = 0 ; i < n ; i++)
{
cin >>id;cin >>score;cin >>school;
for(int j = 0 ; j< school.length() ; j++)
{
if(school[j] >= 'A' && school[j] <= 'Z')
school[j]=tolower(school[j]); //tolower函数,可以把大写转换成小写
}
if(0 == m.count(school)) //如果没出现过 则index++,获取新的下标
{
m[school] = index++;
sch[index-1].school = school;
}
if('B' == id[0]) //分布计算分数,存入学校中
sch[m[school]].score += score /1.5;
else if('A' == id[0])
sch[m[school]].score += score;
else
sch[m[school]].score += score *1.5;
sch[m[school]].num++;
}
sort(sch,sch+index,cmp); //学校排序
cout << index << endl; //打印排名
int flag = 1;
int t = flag; //用来记录名次
cout << t<<" " << sch[0].school<<" " << (int)sch[0].score <<" "<< sch[0].num <<endl;
for(int i = 1 ; i < index; i++)
{
flag++;
if((int)sch[i].score != (int)sch[i-1].score)
t = flag;
cout << t<<" " << sch[i].school<<" " << (int)sch[i].score <<" "<< sch[i].num <<endl;
}
return 0;
}