每次 PAT 考试结束后,考试中心都会发布一个考生单位排行榜。本题就请你实现这个功能。
输入第一行给出一个正整数 N(≤105),即考生人数。随后 N 行,每行按下列格式给出一个考生的信息:
准考证号 得分 学校其中准考证号是由 6 个字符组成的字符串,其首字母表示考试的级别:B代表乙级,A代表甲级,T代表顶级;得分是 [0, 100] 区间内的整数;学校是由不超过 6 个英文字母组成的单位码(大小写无关)。注意:题目保证每个考生的准考证号是不同的。
首先在一行中输出单位个数。随后按以下格式非降序输出单位的排行榜:
排名 学校 加权总分 考生人数其中排名是该单位的排名(从 1 开始);学校是全部按小写字母输出的单位码;加权总分定义为乙级总分/1.5 + 甲级总分 + 顶级总分*1.5的整数部分;考生人数是该属于单位的考生的总人数。
学校首先按加权总分排行。如有并列,则应对应相同的排名,并按考生人数升序输出。如果仍然并列,则按单位码的字典序输出。
思路:一般来说,像这种多条件排序的题一般都要用到结构体,所以我们定义一个结构体,把学校名字,加权总分,人数,顶甲乙级分数作为其信息。再定义一个排序条件。 用map表示该学校是否已存在,一开始输入时,学生准考证号唯一要处理的是第一个字符,所以用字符串string型的来表示学生准考证,输入的学校名字要全部转换成小写字母后再放入该学校的结构里,分数则根据准考证第一个字符进行处理,最后要提的是加权总分留着最后处理。大致代码如下:
#include <iostream> #include <algorithm> #include <cctype> #include <string> #include <vector> #include <map> using namespace std; struct School{ string name; int total=0,people=0,tb=0,ta=0,tt=0; }sch; //学校信息 bool cmp(School a,School b){//排序条件 if(a.total!=b.total) return a.total>b.total; else if(a.people!=b.people) return a.people<b.people; else if(a.name!=b.name) return a.name<b.name; } int main() { int n,score,cnt=1,p=1; string cno,school; //准考证号,学校名字 map<string,int> mp; vector<School> v; //存储学校 cin >>n; for(int i=0;i<n;i++){ cin >>cno>>score>>school; getchar(); for(int j=0;j<school.size();j++) //转小写 school[j]=tolower(school[j]); if(mp[school]==0){ //如果该学校还未出现过 mp[school]=cnt++; sch.name=school; v.push_back(sch); } if(cno[0]=='B') v[mp[school]-1].tb+=score; //按条件计分 else if(cno[0]=='A') v[mp[school]-1].ta+=score; else v[mp[school]-1].tt+=score; v[mp[school]-1].people++; //该学校人数加1 } for(int i=0;i<v.size();i++) //计算加权总分 v[i].total=v[i].tb/1.5+v[i].ta+v[i].tt*1.5; sort(v.begin(),v.end(),cmp); //排序 cout <<v.size()<<endl; printf("%d %s %d %d\n",p,v[0].name.c_str(),v[0].total,v[0].people); for(int i=1;i<v.size();i++){ if(v[i].total!=v[i-1].total) p=i+1; //排名更新 printf("%d %s %d %d\n",p,v[i].name.c_str(),v[i].total,v[i].people); } return 0; }