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.html
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.git
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.函數
2 5 1234567890001 95 1234567890005 100 1234567890003 95 1234567890002 77 1234567890004 85 4 1234567890013 65 1234567890011 25 1234567890014 100 1234567890012 85
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
有n個考場,每一個考場有若干考生。優化
現給出各個考場全部考生的准考證號與分數,要求按分數從高到低分別進行①單考場內排序②總排序。spa
最終輸出參加考試的考生數以及每一個考生的①准考證號②總排名③考場號④考場內排名code
一、排序的邏輯orm
①按分數從高到低排序htm
②分數相同時,按准考證號從小到大排序blog
二、所須要的信息及信息的存儲
①對於單個學生student,須要對應的准考證號id,分數score,考場號location_number,考場內排名local_rank,總排名sum_rank——結構體Student,並建立一個足夠大的結構體數組
②此外還須要總考場數n,總考生數num,單個考場內的考生數k——int型變量
三、排序邏輯的實現
1 bool cmp(Student a, Student b) { 2 if (a.score != b.score) { 3 return a.score > b.score; 4 } else { 5 return strcmp(a.id, b.id) < 0; 6 } 7 }
四、main() 分步分析
主要分爲兩個部分:
(1)給單個考場內的考生排名
①有n個考場,所以最外層要有for循環從1到n遍歷每一個考場
1 for (int i = 1; i <= n; i++) { 2 }
②每一個考場內有k個學生,所以內層要有for循環從0到k-1遍歷每一個學生
1 for (int j = 0; j < k; j++) { 2 }
③接收輸入的准考證號id與分數score,按順序存入結構體數組中
1 scanf("%s %d", stu[num].id, &stu[num].score);
④當前考場的學生遍歷完後,調用排序函數sort()對當前考場內的全部考生按排序邏輯進行排序
1 sort(stu, stu + k, cmp);
⑤按④的排序結果,依次給每一個考生的考場內排名local_rank賦值
1 stu[0].local_rank = 1; //第一個考生的排名爲1 2 for (int j = 1; j < k; j++) { 3 if (stu[j].score == stu[j - 1].score) { 4 stu[j].local_rank = stu[j - 1].local_rank; //分數相同則排名相同 5 } else { 6 stu[j].local_rank = j + 1; //分數不一樣則+1 7 } 8 }
(2)給全部的考生排名
⑥調用排序函數sort()對全部考生按排序邏輯進行排序(代碼同④)
⑦按⑥的排序結果,依次給每一個考生的總排名sum_rank賦值(代碼同⑤)
五、踩到了第一個坑
只開一個Student類型的數組,可是要存放多個考場的考生信息,所以遍歷和排序時不能簡單的從下標0開始
解決:
引入新變量 總考生數num
因而可知,每次接收完一個新考場的考生數據時,此考場考生對應的下標範圍是num - k ~ num
六、main() 雛形
1 scanf("%d", &n); //考場數 2 for (int i = 1; i <= n; i++) { //考場號,要從1開始 3 scanf("%d", &k); //當前考場人數 4 5 /*錄入數據*/ 6 for (int j = 0; j < k; j++) { 7 scanf("%s %d", stu[num].id, &stu[num].score); 8 stu[num].location_number = i; 9 num++; //經過這個計算總考生數 10 } 11 12 /*對剛錄入的這個考場考生進行排序並賦名次*/ 13 sort(stu + num - k, stu + num, cmp); 14 stu[num - k].local_rank = 1; 15 for (int j = num - k + 1; j < num; j++) { 16 if (stu[j].score == stu[j - 1].score) { 17 stu[j].local_rank = stu[j - 1].local_rank; 18 } else { 19 stu[j].local_rank = j + 1 - (num - k);//j爲此考生以前的人數,- (num - k)爲去掉前面其餘考場的人數,+ 1後即獲得此考生在本考場的排名 20 } 21 } 22 23 } 24 25 /*對全部考生進行排序並賦名次*/ 26 sort(stu, stu + num, cmp); 27 stu[0].sum_rank = 1; 28 for (int i = 1; i < num; i++) { 29 if (stu[i].score == stu[i - 1].score) { 30 stu[i].sum_rank = stu[i - 1].sum_rank; 31 } else { 32 stu[i].sum_rank = i + 1; 33 } 34 } 35
七、優化
總排名sum_rank是在整個程序的最後才獲得的
它以後緊跟着的就是要將sum_rank輸出——額外去存儲的意義不大
而且sum_rank的值只有兩種狀況①和前一個相同②i + 1——值的計算簡單,沒有其餘的相關項
因此考慮將「計算出總排名→存入sum_rank→輸出stu[i].sum_rank」簡化爲「計算出總排名→輸出總排名」
1 sort(stu, stu + num, cmp); 2 int r = 1; //r即爲總排名,初始爲1 3 for (int i = 0; i < num; i++) { 4 //i > 0:從第二個考生開始(stu[0]爲第一個考生) 5 //stu[i].score != stu[i - 1].score: 6 //若兩人分數相同,則總排名r相同; 7 //若不一樣,則後一我的的排名爲其前面的人數 i + 1; 8 if (i > 0 && stu[i].score != stu[i - 1].score) { 9 r = i + 1; 10 } 11 }
八、main() 最終形態
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 struct Student { 6 char id[15]; 7 int score; 8 int location_number; 9 int local_rank; 10 int sum_rank; //test 11 }stu[30010]; 12 bool cmp(Student a, Student b) { 13 if (a.score != b.score) { 14 return a.score > b.score; 15 } else { 16 return strcmp(a.id, b.id) < 0; 17 } 18 } 19 int main() { 20 int n, k, num = 0; 21 scanf("%d", &n); 22 for (int i = 1; i <= n; i++) { 23 scanf("%d", &k); 24 for (int j = 0; j < k; j++) { 25 scanf("%s %d", stu[num].id, &stu[num].score); 26 stu[num].location_number = i; 27 num++; 28 } 29 sort(stu + num - k, stu + num, cmp); 30 stu[num - k].local_rank = 1; 31 for (int j = num - k + 1; j < num; j++) { 32 if (stu[j].score == stu[j - 1].score) { 33 stu[j].local_rank = stu[j - 1].local_rank; 34 } else { 35 stu[j].local_rank = j + 1 - (num - k); 36 } 37 } 38 } 39 printf("%d\n", num); 40 sort(stu, stu + num, cmp); 41 int r = 1; 42 for (int i = 0; i < num; i++) { 43 if (i > 0 && stu[i].score != stu[i - 1].score) { 44 r = i + 1; 45 } 46 printf("%s ", stu[i].id); 47 printf("%d %d %d\n", r, stu[i].location_number, stu[i].local_rank); 48 } 49 return 0; 50 }