1025. PAT Ranking (25)
题目如下:
Programming Ability Test (PAT) is organized by the College of Computer Science and Technology of Zhejiang University. Each test is supposed to run simultaneously in several places, and the ranklists will be merged immediately after the test. Now it is your job to write a program to correctly merge all the ranklists and generate the final rank.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive number N (<=100), the number of test locations. Then N ranklists follow, each starts with a line containing a positive integer K (<=300), the number of testees, and then K lines containing the registration number (a 13-digit number) and the total score of each testee. All the numbers in a line are separated by a space.
Output Specification:
For each test case, first print in one line the total number of testees. Then print the final ranklist in the following format:
registration_number final_rank location_number local_rank
The locations are numbered from 1 to N. The output must be sorted in nondecreasing order of the final ranks. The testees with the same score must have the same rank, and the output must be sorted in nondecreasing order of their registration numbers.
Sample Input:2 5 1234567890001 95 1234567890005 100 1234567890003 95 1234567890002 77 1234567890004 85 4 1234567890013 65 1234567890011 25 1234567890014 100 1234567890012 85Sample Output:
9 1234567890005 1 1 1 1234567890014 1 2 1 1234567890001 3 1 2 1234567890003 3 1 2 1234567890004 5 1 4 1234567890012 5 2 2 1234567890002 7 1 5 1234567890013 8 2 3 1234567890011 9 2 4
题目要求对数据分别按照地区、全区排名,并且按照名字顺序输出。
我们可以建立一个Person结构体,存储ID、分数、地区号、地区排名。
题目的难点主要在于排名算法和地区、全区分别排名,下面分别讨论。
①排名算法:
首先对所有数据按降序排序,然后相同分数的作为同一个名次,分数不同的时候排名要根据前面相同分数的人数来计算,具体算法如下:
首先利用vector<Person> ps来作为数据容器,先将一个地区的所有数据压入,然后使用sort函数排序,为了满足题目条件,在定义compare函数时应该注意不仅考虑分数高低,还要考虑人名的字典顺序。
sort函数接受compare函数指针,对于元素a、b,系统默认当a < b时应该为true(默认用<比较,升序),为了按分数降序、人名升序,作如下修改:
bool compare(Person a,Person b) // 对sort函数指定比较规则,首先是名字按照字典顺序排序,如果名字相同则按时间顺序 { if(a.score > b.score){ return true; }else if(a.score == b.score){ if(a.name < b.name){ return true; }else{ return false; } } return false; }排序结束后,分数是按递减顺序分布的,接下来计算排名。定义变量nowScore、rk、numCnt,其中nowScore代表当前计算排名的分数,rk代表当前分数的排名、numCnt代表人数计数器,首先初始化nowScore为第一个人的成绩,也就是最高分,rk初始化为1,numCnt为1,当后面的成绩等于nowScore时,仅把numCnt+1,代表这一分段的人数,当nowScore不等于某个人的分数时,说明到了下一个分数档次,这时候rk等于numCnt,即可得到这个分段的初始排名,同时把nowScore置为这个分数,numCnt不要忘记+1,因为这也是一个人,排名计算具体方法为:
初始化:
int nowScore = all[0].score; int rk = 1; int numCnt = 1;动态计算:注意这里是在这段代码后将rk直接输出,因此没有把rk赋值给其他变量。
Person p = all[i]; if(nowScore != p.score){ rk = numCnt; nowScore = p.score; numCnt++; }else{ numCnt++; }
②分区排名的算法:
定义两个vector<Person> ps,all;
在一个区的开始,清空ps,然后压入所有数据到ps,排序,接下来从前到后遍历ps,取出Person计算排名,在每个Person中有个单元local_rank用来记录自己的排名,然后把计算之后的Person压入all,一个区结束后再开始下个区,在所有区计算后all中的每个元素都记录着自己的地区排名,这时候只要把all中元素再排序,计算总排名,在输出时即可实现两个排名的输出。
完整源码如下:
#include <iostream> #include <vector> #include <algorithm> #include <string.h> #include <string> using namespace std; struct Person{ string name; int score; int local_rank; int local_num; Person(string _n, int _s): name(_n), score(_s) {} }; bool compare(Person a,Person b) // 对sort函数指定比较规则,首先是名字按照字典顺序排序,如果名字相同则按时间顺序 { if(a.score > b.score){ return true; }else if(a.score == b.score){ if(a.name < b.name){ return true; }else{ return false; } } return false; } using namespace std; int main() { vector<Person> ps; vector<Person> all; int N,K; string name; int score; cin >> N; int i,j,k; for(i = 0; i < N; i++){ cin >> K; ps.clear(); for(j = 0; j < K; j++ ){ cin >> name >> score; ps.push_back(Person(name,score)); } sort(ps.begin(),ps.end(),compare); int nowScore = ps[0].score; int rk = 1; int numCnt = 1; for(k = 0; k < ps.size(); k++){ Person p = ps[k]; p.local_num = i + 1; if(p.score != nowScore){ nowScore = p.score; rk = numCnt; numCnt++; }else{ numCnt++; } p.local_rank = rk; all.push_back(p); } } sort(all.begin(),all.end(),compare); int nowScore = all[0].score; int rk = 1; int numCnt = 1; cout << all.size() << endl; for(i = 0; i < all.size(); i++) { Person p = all[i]; if(nowScore != p.score){ rk = numCnt; nowScore = p.score; numCnt++; }else{ numCnt++; } cout << p.name << " " << rk << " " << p.local_num << " " << p.local_rank << endl; } return 0; }