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 85

Sample 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
 

题意:

有n个考场,每个考场有若干考生。

现给出各个考场所有考生的准考证号与分数,要求按分数从高到低分别进行①单考场内排序②总排序。

最终输出参加考试的考生数以及每个考生的①准考证号②总排名③考场号④考场内排名

 

思路:

1、排序的逻辑

①按分数从高到低排序

②分数相同时,按准考证号从小到大排序

2、所需要的信息及信息的存储

①对于单个学生student,需要对应的准考证号id,分数score,考场号location_number,考场内排名local_rank,总排名sum_rank——结构体Student,并创建一个足够大的结构体数组

②此外还需要总考场数n,总考生数num,单个考场内的考生数k——int型变量

3、排序逻辑的实现

 bool cmp(Student a, Student b) {
if (a.score != b.score) {
return a.score > b.score;
} else {
return strcmp(a.id, b.id) < ;
}
}

4、main()  分步分析

主要分为两个部分:

(1)给单个考场内的考生排名

①有n个考场,因此最外层要有for循环从1到n遍历每个考场

 for (int i = ; i <= n; i++) {
}

②每个考场内有k个学生,因此内层要有for循环从0到k-1遍历每个学生

 for (int j = ; j < k; j++) {
}

③接收输入的准考证号id与分数score,按顺序存入结构体数组中

 scanf("%s %d", stu[num].id, &stu[num].score);

④当前考场的学生遍历完后,调用排序函数sort()对当前考场内的所有考生按排序逻辑进行排序

 sort(stu, stu + k, cmp);

⑤按④的排序结果,依次给每个考生的考场内排名local_rank赋值

 stu[].local_rank = ;  //第一个考生的排名为1
for (int j = ; j < k; j++) {
if (stu[j].score == stu[j - ].score) {
stu[j].local_rank = stu[j - ].local_rank; //分数相同则排名相同
} else {
stu[j].local_rank = j + ; //分数不同则+1
}
}

(2)给所有的考生排名

⑥调用排序函数sort()对所有考生按排序逻辑进行排序(代码同④)

⑦按⑥的排序结果,依次给每个考生的总排名sum_rank赋值(代码同⑤)

5、踩到了第一个坑

只开一个Student类型的数组,但是要存放多个考场的考生信息,因此遍历和排序时不能简单的从下标0开始

解决:

引入新变量 总考生数num

于是可知,每次接收完一个新考场的考生数据时,此考场考生对应的下标范围是num - k ~ num

6、main()  雏形

 scanf("%d", &n); //考场数
for (int i = ; i <= n; i++) { //考场号,要从1开始
scanf("%d", &k); //当前考场人数 /*录入数据*/
for (int j = ; j < k; j++) {
scanf("%s %d", stu[num].id, &stu[num].score);
stu[num].location_number = i;
num++; //通过这个计算总考生数
} /*对刚录入的这个考场考生进行排序并赋名次*/
sort(stu + num - k, stu + num, cmp);
stu[num - k].local_rank = ;
for (int j = num - k + ; j < num; j++) {
if (stu[j].score == stu[j - ].score) {
stu[j].local_rank = stu[j - ].local_rank;
} else {
stu[j].local_rank = j + - (num - k);//j为此考生之前的人数,- (num - k)为去掉前面其他考场的人数,+ 1后即得到此考生在本考场的排名
}
} } /*对所有考生进行排序并赋名次*/
sort(stu, stu + num, cmp);
stu[].sum_rank = ;
for (int i = ; i < num; i++) {
if (stu[i].score == stu[i - ].score) {
stu[i].sum_rank = stu[i - ].sum_rank;
} else {
stu[i].sum_rank = i + ;
}
}

7、优化

总排名sum_rank是在整个程序的最后才得到的

它之后紧跟着的就是要将sum_rank输出——额外去存储的意义不大

并且sum_rank的值只有两种情况①和前一个相同②i + 1——值的计算简单,没有其他的相关项

所以考虑将“计算出总排名→存入sum_rank→输出stu[i].sum_rank”简化为“计算出总排名→输出总排名”

 sort(stu, stu + num, cmp);
int r = ; //r即为总排名,初始为1
for (int i = ; i < num; i++) {
//i > 0:从第二个考生开始(stu[0]为第一个考生)
//stu[i].score != stu[i - 1].score:
//若两人分数相同,则总排名r相同;
//若不同,则后一个人的排名为其前面的人数 i + 1;
if (i > && stu[i].score != stu[i - ].score) {
r = i + ;
}
}

8、main() 最终形态

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Student {
char id[];
int score;
int location_number;
int local_rank;
int sum_rank; //test
}stu[];
bool cmp(Student a, Student b) {
if (a.score != b.score) {
return a.score > b.score;
} else {
return strcmp(a.id, b.id) < ;
}
}
int main() {
int n, k, num = ;
scanf("%d", &n);
for (int i = ; i <= n; i++) {
scanf("%d", &k);
for (int j = ; j < k; j++) {
scanf("%s %d", stu[num].id, &stu[num].score);
stu[num].location_number = i;
num++;
}
sort(stu + num - k, stu + num, cmp);
stu[num - k].local_rank = ;
for (int j = num - k + ; j < num; j++) {
if (stu[j].score == stu[j - ].score) {
stu[j].local_rank = stu[j - ].local_rank;
} else {
stu[j].local_rank = j + - (num - k);
}
}
}
printf("%d\n", num);
sort(stu, stu + num, cmp);
int r = ;
for (int i = ; i < num; i++) {
if (i > && stu[i].score != stu[i - ].score) {
r = i + ;
}
printf("%s ", stu[i].id);
printf("%d %d %d\n", r, stu[i].location_number, stu[i].local_rank);
}
return ;
}

【算法学习记录-排序题】【PAT A1025】PAT Ranking的更多相关文章

  1. 【算法学习记录-排序题】【PAT A1012】The Best Rank

    To evaluate the performance of our first year CS majored students, we consider their grades of three ...

  2. 【算法学习记录-排序题】【PAT A1016】Phone Bills

    A long-distance telephone company charges its customers by the following rules: Making a long-distan ...

  3. 【算法学习记录-排序题】【PAT A1062】Talent and Virtue

    About 900 years ago, a Chinese philosopher Sima Guang wrote a history book in which he talked about ...

  4. 算法学习记录-排序——插入排序(Insertion Sort)

    插入排序: 在<算法导论>中是这样描述的 这是一个对少量元素进行排序的有效算法.插入排序的工作机理与打牌时候,整理手中的牌做法差不多. 在开始摸牌时,我们的左手是空的,牌面朝下放在桌子上. ...

  5. 算法学习记录-排序——冒泡排序(Bubble Sort)

    冒泡排序应该是最常用的排序方法,我接触的第一个排序算法就是冒泡,老师也经常那这个做例子. 冒泡排序是一种交换排序, 基本思想: 通过两两比较相邻的记录,若反序则交换,知道没有反序的记录为止. 例子: ...

  6. 算法学习记录-排序——选择排序(Simple Selection Sort)

    之前在冒泡排序的附录中提到可以在每次循环时候,不用交换操作,而只需要记录最小值下标,每次循环后交换哨兵与最小值下标的书, 这样可以减少交换操作的时间. 这种方法针对冒泡排序中需要频繁交换数组数字而改进 ...

  7. 算法学习记录-图——应用之拓扑排序(Topological Sort)

    这一篇写有向无环图及其它的应用: 清楚概念: 有向无环图(DAG):一个无环的有向图.通俗的讲就是从一个点沿着有向边出发,无论怎么遍历都不会回到出发点上. 有向无环图是描述一项工程或者系统的进行过程的 ...

  8. 算法学习 拓扑排序(TopSort)

    拓扑排序 一.基本概念 在一个有向无环图(Directed Acyclic Graph, DAG)中,规定< u,v > 表示一条由u指向v的的有向边.要求对所有的节点排序,使得每一条有向 ...

  9. Manacher回文串算法学习记录

    FROM:  http://hi.baidu.com/chenwenwen0210/item/482c84396476f0e02f8ec230 #include<stdio.h> #inc ...

随机推荐

  1. Thingsboard之MQTT设备协议简介

    MQTT基础知识 MQTT是一种轻量级的发布 - 订阅消息传递协议,可能使其最适合各种物联网设备.您可以在此处找到有关MQTT的更多信息.ThingsBoard服务器节点充当MQTT Broker,支 ...

  2. 后端跨域的N种方法

    简单来说,CORS是一种访问机制,英文全称是Cross-Origin Resource Sharing,即我们常说的跨域资源共享,通过在服务器端设置响应头,把发起跨域的原始域名添加到Access-Co ...

  3. 《手把手教你构建自己的 Linux 系统》学习笔记(7)

    目录 tee 命令的缺陷是什么?如何解决这个缺陷? /etc/ld.so.conf 文件的作用是什么? 动态链接和静态链接有什么不同? 动态编译 静态编译 共享库为什么会有版本?共享库的版本升级原理是 ...

  4. 退役记——CCC2020&CCO2020

    我叫吴佳诚,一个曾在福建师大附中就读的oier,2019年7月份我来到多伦多就读于Langstaff Secondary School 我的常用id有:Johnson_Wu,温词 竞赛经历: 2018 ...

  5. 在 Nest.js 中使用 MongoDB 与 TypeORM

    在 Nest.js 中使用 MongoDB 与 TypeORM 首先要在 database 文件夹里建立DatabaseModule模块文件, // database/database.module. ...

  6. .net core 3.0一个记录request和respose的中间件

    参考资料 https://www.cnblogs.com/wybin6412/p/10944077.html RequestResponseLog.cs using System; using Sys ...

  7. day7 基础数据类型&集合&深浅拷贝

    基础数据类型汇总: #!/usr/bin/env python # -*- coding:utf-8 -*- ''' str int ''' # str s = ' a' print(s.isspac ...

  8. CF #619 div.2

    序 希望,不要还有一天像今天一样糟糕. T1 three strings 笔记本的google 炸了,读题可难受了 多组测试数据 我们的想法是,用string存字符串,若 对于任意的i,a[i],b[ ...

  9. @Autowired、@Resource、@Qualifier区别

    @Autowired 1.属于spring的注解,如果不想和Spring耦合的太紧,就不推荐使用. 2.默认情况下,要求依赖对象必须存在,不能为null.如果允许为空,那么设置属性值required为 ...

  10. 谈一谈php反序列化

    1.序列化与反序列化 php中有两个函数serialize()和unserialize() 序列化serialize(): 当在php中创建了一个对象后,可以通过serialize()把这个对象转变成 ...