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. Uva12716 素数筛思想的应用

    Uva12716 题意: 输入整数n,1<= n <=3e7,问有多少个整数对(a,b)满足:1 <= b <= a <= n,且gcd(a,b)== a XOR b 解 ...

  2. 在Django中使用Sentry(Python 3.6.8 + Django 1.11.20 + sentry-sdk 0.13.5)

    1. 安装Sentry pip install sentry-sdk==0.13.5 2.在settings.py中配置 sentry_sdk.init( dsn="https://**** ...

  3. node-sass pip 安装报错,提示缺少python2

    解决办法参考https://segmentfault.com/a/1190000010984731?utm_source=tag-newest npm uninstall node-sass npm ...

  4. gulp常用插件之gulp-rev-delete-origina使用

    更多gulp常用插件使用请访问:gulp常用插件汇总 gulp-rev-delete-origina这是一款删除由gulp-rev或 gulp-rev-all重写的原始文件 . 更多使用文档请点击访问 ...

  5. web渗透漏洞靶场收集

    最近将自己遇到过或者知道的web靶场链接奉上 0X01 DVWA 推荐新手首选靶场,配置简单,需下载phpstudy和靶场文件包,简单部署之后即可访问. 包含了常见的web漏洞(php的),每个漏洞分 ...

  6. H3C IP地址配置

    一.IP地址分类 分配地址就是给每个连接到IPv4网络上的设备分配的一个网络唯一的地址.IP地址长度为32比特,通常采用点分十进制方式表示,即每个IP地址被表示为以小数点隔开的4个十进制整数,每个整数 ...

  7. 7-5 A除以B(10 分)

    真的是简单题哈 —— 给定两个绝对值不超过100的整数A和B,要求你按照“A/B=商”的格式输出结果. 输入格式:输入在第一行给出两个整数A和B(−100≤A,B≤100),数字间以空格分隔. 输出格 ...

  8. 关于华为高斯数据库 GaussDB 版本及认证体系介绍

    目录 你需要知道的 技术有国界 从它的名称说起 你听到过的版本 你听到过的流言蜚语 各个版本的区别 版本未来名称 华为 GaussDB 认证体系介绍 GaussDB 其他资料相关链接 你需要知道的 任 ...

  9. vsftpd最详细的配置文件

    vsftpd作为一个主打安全的FTP服务器,有很多的选项设置.下面介绍了vsftpd的配置文件列表,而所有的配置都是基于vsftpd.conf这个配置文件的.本文将提供完整的vsftpd.conf的中 ...

  10. 【Unity|C#】基础篇(16)——文件读写(I/O类)

    [笔记] 文件操作 File / FileInfo / FileStream https://www.runoob.com/csharp/csharp-file-io.html 文本读写 Stream ...