To evaluate the performance of our first year CS majored students, we consider their grades of three courses only: C - C Programming Language, M - Mathematics (Calculus or Linear Algrbra), and E - English. At the mean time, we encourage students by emphasizing on their best ranks -- that is, among the four ranks with respect to the three courses and the average grade, we print the best rank for each student.

For example, The grades of C, M, E and A - Average of 4 students are given as the following:

StudentID  C  M  E  A
310101 98 85 88 90
310102 70 95 88 84
310103 82 87 94 88
310104 91 91 91 91
 

Then the best ranks for all the students are No.1 since the 1st one has done the best in C Programming Language, while the 2nd one in Mathematics, the 3rd one in English, and the last one in average.

Input Specification:

Each input file contains one test case. Each case starts with a line containing 2 numbers N and M (≤2000), which are the total number of students, and the number of students who would check their ranks, respectively. Then N lines follow, each contains a student ID which is a string of 6 digits, followed by the three integer grades (in the range of [0, 100]) of that student in the order of C, M and E. Then there are M lines, each containing a student ID.

Output Specification:

For each of the M students, print in one line the best rank for him/her, and the symbol of the corresponding rank, separated by a space.

The priorities of the ranking methods are ordered as A > C > M > E. Hence if there are two or more ways for a student to obtain the same best rank, output the one with the highest priority.

If a student is not on the grading list, simply output N/A.

Sample Input:

5 6
310101 98 85 88
310102 70 95 88
310103 82 87 94
310104 91 91 91
310105 85 90 90
310101
310102
310103
310104
310105
999999
 

Sample Output:

1 C
1 M
1 E
1 A
3 A
N/A

题意:

n个学生,现分别给出每个学生的3科成绩C、M、E,又有A为平均分

给出m个查询,输入学生ID,输出A、C、M、E中最高的排名及对应的是哪个

①若多个排名相同,则按A>C>M>E输出最高优先级的

②若查询的学生ID不存在,则输出N/A

思路:

0、对比分析

【A1012】在《算法笔记(胡凡)》中,按训练顺序是排在【A1025】和【A1062】两道排序题之后

因为那两题是最基础的仅单项数据的排序,而这一题扩展到了多项(4项)数据的排序

在刚看到这题时因为要进行多项数据的排序而陷入了混乱

现在复盘梳理时,我认为 从 单项数据排序 扩展到 多项数据排序 的思路会更加清晰且易于理解

1、先从单项数据排序开始

我们假设现在只有一门科目X

①结构体

 struct Student {
int id; //学生id
int grade; //分数
}stu[];  //题目给出N《=2000

②排序函数cmp

 bool cmp(Student a, Student b) {
return a.grade> b.grade;
}

③存放排名的数组Rank(※这里踩过一个坑:rank是关键字,所以要写作Rank)

在之前的【A1025】和【A1062】中,id只用于输出,故都是常规地使用char类型数组存放

而这一题中,id要担当从 分数Student.grade 到 排名Rank 的对应 的责任

如果在Student中将id设为char[6],那Rank中就既要存放int型的排名,又要存放char[]型的id——显然,就算强行实现,也非常麻烦

考虑到题目中的id为6位0-9的数字,故我们将id设为int类型,而Rank的大小则开为[1000000],其下标就包含了100000~999999的所有可能的ID

即Rank[Student.id] = Student.grade,每个下标对应的即为此ID学生的排名

 int Rank[] = {};

④main()

 int main() {
//总计有n个学生,m个查询
scanf("%d%d", &n, &m);
for (int i = ; i < n; i++) {
scanf("%d%d", &stu[i].id, &stu[i].grade);
}
//对n个学生的成绩进行排序
sort(stu, stu + n, cmp);
//第一名的排名为1
Rank[stu[].id] = ;
//剩下学生的排名
for (int i = ; i < n; i++) {
if (stu[i].grade == stu[i - ].grade) {
Rank[stu[i].id] = Rank[stu[i - ].id];
} else {
Rank[stu[i].id] = i + ;
}
}
//m个查询
for (int i = ; i < m; i++) {
scanf("%d", &query);
if (Rank[query] == ) {
printf("N/A\n");
} else {
printf("%d %c\n", Rank[query]);
}
}
return ;
}

2、再扩展到多项数据排序

①结构体修改

 struct Student {
int id;
int grade[];
}stu[];

②排序函数cmp修改

 int now;    //标识当前是A、C、M、E中的哪个科目

 bool cmp(Student a, Student b) {
return a.grade[now] > b.grade[now];
}

③还需要的两个数组

 char course[] = {'A', 'C', 'M', 'E'};    //按优先级排序更方便

 int Rank[][] = {};

④main() : 录入成绩

 for (int i = ; i < n; i++) {
scanf("%d%d%d%d", &stu[i].id, &stu[i].grade[], &stu[i].grade[], &stu[i].grade[]); //C、M、E
stu[i].grade[] = round((stu[i].grade[] + stu[i].grade[] + stu[i].grade[]) / 3.0) + 0.5; //A
}

⑤main() : 排名

 for (now = ; now < ; now++) {    //四个科目分别排

     //内部就和单数据排序相同了
sort(stu, stu + n, cmp);
Rank[stu[].id][now] = ;
for (int i = ; i < n; i++) {
if (stu[i].grade[now] == stu[i - ].grade[now]) {
Rank[stu[i].id][now] = Rank[stu[i - ].id][now];
} else {
Rank[stu[i].id][now] = i + ;
}
} }

⑥main() : 查询

 for (int i = ; i < m; i++) {
scanf("%d", &query);
if (Rank[query][] == ) {
printf("N/A\n");
} else {
int k = ;  //因有A>C>M>E的优先级,故这里设初值0
for (int j = ; j < ; j++) {
if (Rank[query][j] < Rank[query][k]) {
k = j;
}
}
printf("%d %c\n", Rank[query][k], course[k]);
}
}

3、题解

 #include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
struct Student {
int id;
int grade[];
}stu[]; char course[] = {'A', 'C', 'M', 'E'};
int Rank[][] = {};
int now; bool cmp(Student a, Student b) {
return a.grade[now] > b.grade[now];
}
int main() {
int n, m, query;
scanf("%d%d", &n, &m);
for (int i = ; i < n; i++) {
scanf("%d%d%d%d", &stu[i].id, &stu[i].grade[], &stu[i].grade[], &stu[i].grade[]);
stu[i].grade[] = round((stu[i].grade[] + stu[i].grade[] + stu[i].grade[]) / 3.0) + 0.5;
}
for (now = ; now < ; now++) {
sort(stu, stu + n, cmp);
Rank[stu[].id][now] = ;
for (int i = ; i < n; i++) {
if (stu[i].grade[now] == stu[i - ].grade[now]) {
Rank[stu[i].id][now] = Rank[stu[i - ].id][now];
} else {
Rank[stu[i].id][now] = i + ;
}
}
}
for (int i = ; i < m; i++) {
scanf("%d", &query);
if (Rank[query][] == ) {
printf("N/A\n");
} else {
int k = ;
for (int j = ; j < ; j++) {
if (Rank[query][j] < Rank[query][k]) {
k = j;
}
}
printf("%d %c\n", Rank[query][k], course[k]);
}
}
return ;
}

【算法学习记录-排序题】【PAT A1012】The Best Rank的更多相关文章

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

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

  2. 【算法学习记录-排序题】【PAT A1025】PAT Ranking

    Programming Ability Test (PAT) is organized by the College of Computer Science and Technology of Zhe ...

  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. 获取现有Table中某些字段

    //dtH System.Data.DataTable dttemp = new System.Data.DataTable(); DataView tempDv = dtH.DefaultView; ...

  2. js里cookie,localStorage的简单用法

    cookie的使用场景---->注册功能(注册成功后,将账号和密码存入cookie里,在登录时显示到输入框里) 注册的js(将数据存入cookie):        escape和unescap ...

  3. drf 接口文档

    coreapi 参考点击 swagger风格接口文档 参考 参考用例 swagger 使用参考

  4. [PAT] A1017 Queueing at Bank

    [思路] 1:将所有满足条件的(到来时间点在17点之前的)客户放入结构体中,结构体的长度就是需要服务的客户的个数.结构体按照到达时间排序. 2:wend数组表示某个窗口的结束时间,一开始所有窗口的值都 ...

  5. css中content-box和border-box当宽度为百分比时的位置区别,vw和%区别

    盒模型 参考代码 // CSS 部分 <style> .box1,.box2{ width: 200px; height: 200px; padding: 20px; margin: 20 ...

  6. 使用_slots_变量限制class实例能添加的属性

    如果我们想要限制实例的属性怎么办?比如,只允许对Student实例添加name和age属性. 那么我们在Student类里面增添_slots_变量 例如: class Student(object): ...

  7. 从首个IMO季军谈起 作者 : 付云皓

    刚刚过去的IMO,中国史无前例地获得了第三名,也是自1997年来近20年首次跌出前二.感谢微信等社交软件,相信现在这个新闻已经以火箭的速度传播了. 作为一个与数学竞赛及IMO打了多年交道的人,我一直有 ...

  8. [POI2010] GIL-Guilds - 二分图染色,DFS

    给一张无向图,要求你用黑白灰给点染色,且满足对于任意一个黑点,至少有一个白点和他相邻:对于任意一个白点,至少有一个黑点与他相邻,对于任意一个灰点,至少同时有一个黑点和白点和灰点与他相邻,问能否成功 S ...

  9. 支付宝网站支付接口配置 RSA 公钥 私钥

    个人博客 地址:http://www.wenhaofan.com/article/20190419143333 下载签名工具 访问:https://docs.open.alipay.com/291/1 ...

  10. Github+Hexo一站式部署个人博客(原创)

    写在前面 注:博主 Chloneda:个人博客 | 博客园 | Github | Gitee | 知乎 本文源链接:https://www.cnblogs.com/chloneda/p/hexo.ht ...