【算法学习记录-排序题】【PAT A1012】The Best Rank
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的更多相关文章
- 【算法学习记录-排序题】【PAT A1016】Phone Bills
A long-distance telephone company charges its customers by the following rules: Making a long-distan ...
- 【算法学习记录-排序题】【PAT A1025】PAT Ranking
Programming Ability Test (PAT) is organized by the College of Computer Science and Technology of Zhe ...
- 【算法学习记录-排序题】【PAT A1062】Talent and Virtue
About 900 years ago, a Chinese philosopher Sima Guang wrote a history book in which he talked about ...
- 算法学习记录-排序——插入排序(Insertion Sort)
插入排序: 在<算法导论>中是这样描述的 这是一个对少量元素进行排序的有效算法.插入排序的工作机理与打牌时候,整理手中的牌做法差不多. 在开始摸牌时,我们的左手是空的,牌面朝下放在桌子上. ...
- 算法学习记录-排序——冒泡排序(Bubble Sort)
冒泡排序应该是最常用的排序方法,我接触的第一个排序算法就是冒泡,老师也经常那这个做例子. 冒泡排序是一种交换排序, 基本思想: 通过两两比较相邻的记录,若反序则交换,知道没有反序的记录为止. 例子: ...
- 算法学习记录-排序——选择排序(Simple Selection Sort)
之前在冒泡排序的附录中提到可以在每次循环时候,不用交换操作,而只需要记录最小值下标,每次循环后交换哨兵与最小值下标的书, 这样可以减少交换操作的时间. 这种方法针对冒泡排序中需要频繁交换数组数字而改进 ...
- 算法学习记录-图——应用之拓扑排序(Topological Sort)
这一篇写有向无环图及其它的应用: 清楚概念: 有向无环图(DAG):一个无环的有向图.通俗的讲就是从一个点沿着有向边出发,无论怎么遍历都不会回到出发点上. 有向无环图是描述一项工程或者系统的进行过程的 ...
- 算法学习 拓扑排序(TopSort)
拓扑排序 一.基本概念 在一个有向无环图(Directed Acyclic Graph, DAG)中,规定< u,v > 表示一条由u指向v的的有向边.要求对所有的节点排序,使得每一条有向 ...
- Manacher回文串算法学习记录
FROM: http://hi.baidu.com/chenwenwen0210/item/482c84396476f0e02f8ec230 #include<stdio.h> #inc ...
随机推荐
- 卸载Windows控制面板的程序和功能中找不到的一些软件的方法
卸载Windows控制面板的程序和功能中找不到的一些软件的方法 找到卸载程序进行卸载即可
- Java数列循环左移
描述 有n个整数组成一个数组(数列).现使数列中各数顺序依次向左移动k个位置,移出的数再从尾部移入.输出移动后的数列元素. 题目没有告诉你n的范围,要求不要提前定义数组的大小. 另外要求定义并使用函数 ...
- win10子系统ubuntu忘记密码解决方案
准备部署一个rocket.chat 需要安装mongodb 3.6 准备直接在子系统中安装一下,结果忘记ROOT密码了 找了一下子系统重置密码 记录如下 ubuntu config --defau ...
- ASP.NET MVC 方法View返回的两种方式
1.参数为字符串类型 例如我们在地址栏输入http://localhost:56431/Test/Index,会查找TestController类下的Index方法并执行,如下图 当我们返回字符串类型 ...
- 支付宝网站支付接口配置 RSA 公钥 私钥
个人博客 地址:http://www.wenhaofan.com/article/20190419143333 下载签名工具 访问:https://docs.open.alipay.com/291/1 ...
- 看完它,你就全懂了十大Wifi芯片原厂!
看完它,你就全懂了十大Wifi芯片原厂! 来源:全球物联网观察 概要:不知不觉中,WiFi几乎已攻占了整个世界.现在只要你上网,可能就离不开WiFi了. 2014年是物联网WiFi市场关键的转折期 ...
- set类型的应用场景 —— Redis实战经验
set类型是string类型的集合,其特点是集合元素无序且不重复,每个集合最多可以存储 232 - 1 个元素(40多亿),set类型主要有以下应用场景. 1. 好友/关注/粉丝/感兴趣的人集合 se ...
- Windows Server多用户同时远程登录
因为工作需要,需要使用windwos作为一个远程登录跳板机,管理员对登录windwos机器再windwos的基础上连接别的机器,普通用户也可以连接windwos机器再连接别的机器,关于管理员普通用户连 ...
- VSCode常用插件之EditorConfig for vs code 使用
更多VSCode插件使用请访问:VSCode常用插件汇总 当大家在公司工作时,不可能永远是一个人维护一个项目,当多个人参与一个项目,每个人使用的编辑器不一样,代码风格自然也不一样,那么如何让使用不同编 ...
- prach 839滤波系数