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. Vue自定义全局Toast和Loading

    如果我们的Vue项目中没有用到任何UI框架的话,为了更好的用户体验,肯定会用到loading和toast.那么我们就自定义这两个组件吧. 1.Toast组件 首先,在common下新建global文件 ...

  2. SGDClassifier梯度下降分类方法

    SGDClassifier梯度下降分类方法 这个分类器跟其他线性分类器差不多,只是它用的是mini-batch来做梯度下降,在处理大数据的情况下收敛更快 1.应用 SGD主要应用在大规模稀疏数据问题上 ...

  3. Mac下安装MySQL8的问题

    黑苹果用了一段时间之后,发现很多方面用起来比Windows还舒服些,没什么具体指标,就是纯粹一种感觉. 所以,慢慢将很多程序都迁移过来,在迁移过程中发现的一些有意思的事儿,我都把他们记录下来.如果,不 ...

  4. Android 存档最优选项

    1 开发环境:VS2019最新版本(16.4.5) 2  存档最优选项 说明:apk包70M(默认选项),apk包12M(调整后选项) 位置:Android 选项

  5. Nessus 8.2.3无IP限制VM版虚拟机

    根据“西门吹雪”http://ximcx.cn/m/?post=151的文章自己下载配置的过程 VM版本>=12都行,我用的是VM14 下载地址 https://moehu-my.sharepo ...

  6. PTA 1003 Emergency

    问题描述 As an emergency rescue team leader of a city, you are given a special map of your country. The ...

  7. [CF1303C] Perfect Keyboard - DFS

    Solution 根据原字符串建图,每个字符是一个点,相邻则连边 然后从每一个度数为 \(1\) 的点开始爆搜连通块,合法情况下应该是一条链 #include <bits/stdc++.h> ...

  8. zedboard通过BRAM实现PS和PL的简单通信

    使用Block Memory进行PS和PL的数据交互或者数据共享,通过zynq PS端的Master GP0端口向BRAM写数据,然后再通过PS端的Mater GP1把数据读出来,将结果打印输出到串口 ...

  9. cookie、session和application

    https://cloud.tencent.com/developer/article/1493869 前言: 一直想写一篇关于cookie和session的博客,由于种种原因,一直没有整理,这不,今 ...

  10. 51nod(1089 最长回文子串 V2)(hash 加二分)

    1089 最长回文子串 V2(Manacher算法)   回文串是指aba.abba.cccbccc.aaaa这种左右对称的字符串. 输入一个字符串Str,输出Str里最长回文子串的长度.   输入 ...