1012 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
分析
本题的基本思路其实不太难,就是对数据按照要求进行排序即可。但是细节部分问题比较多,不注意的话无法拿到所有分数。首先,对于A,题目中没有说明是否需要四舍五入,因此有一个很巧妙的处理方法,就是只存储总分不计算平均值(题目中只要求排名),这样得出的排名必然是对的。如果一定要计算平均分,可以使用库函数或者加0.5再直接取整。第二就是这个排名,如果有并列的情况,排名不能顺延而是直接按照人数排名,即:1 1 3 4 5
。最后就是这个变量的存储问题,本题设计的变量较多,4个分数,4个排名,可以直接存储在数组中,如果单独明明代码重复太大(前两天我还说别人来着。。。)本题就是麻烦点,注意细节。(但我确实没调出来。。)
代码
#include <cstdio>
#include <algorithm>
using namespace std;
struct node {
int id, best; // best存储最优排名的下标
int score[4], rank[4]; // A C M E
}stu[2005];
int exist[1000000], flag = -1; // exist 用来判断是否存在
bool cmp1(node a, node b) {return a.score[flag] > b.score[flag];}
int main() {
int n, m, id;
scanf("%d %d", &n, &m);
for(int i = 0; i < n; i++) {
scanf("%d %d %d %d", &stu[i].id, &stu[i].score[1], &stu[i].score[2], &stu[i].score[3]);
stu[i].score[0] = (stu[i].score[1] + stu[i].score[2] + stu[i].score[3]) / 3.0 + 0.5;
}
for(flag = 0; flag <= 3; flag++) { // flag用来确定当前排序的是哪个分数
sort(stu, stu + n, cmp1);
stu[0].rank[flag] = 1;
for(int i = 1; i < n; i++) {
stu[i].rank[flag] = i + 1;
if(stu[i].score[flag] == stu[i-1].score[flag])
stu[i].rank[flag] = stu[i-1].rank[flag];
}
}
for(int i = 0; i < n; i++) {
exist[stu[i].id] = i + 1;
stu[i].best = 0;
int minn = stu[i].rank[0];
for(int j = 1; j <= 3; j++) { //这里是求排名的最小值
if(stu[i].rank[j] < minn) {
minn = stu[i].rank[j];
stu[i].best = j;
}
}
}
char c[5] = {'A', 'C', 'M', 'E'};
for(int i = 0; i < m; i++) {
scanf("%d", &id);
int temp = exist[id];
if(temp) {
int best = stu[temp-1].best;
printf("%d %c\n", stu[temp-1].rank[best], c[best]);
} else {
printf("N/A\n");
}
}
return 0;
}