PAT A1012. The Best Rank

Time Limit: 400ms                              Memory Limit:65636 KB

题目描述(原题为英文):
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 Algebra),
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:

(机翻:为了评估我们CS专业一年级学生的表现,我们考虑他们的成绩

三门课程:C -C编程语言,M -数学(微积分或线性代数),

和E -英语。同时,我们鼓励学生强调他们最好的排名-

也就是说,在四个排名中,关于三门课程和平均成绩,我们打印

每个学生最好的排名。

例如,C,M,E和A的成绩——4个学生的平均成绩:)

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.I 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.
输入格式
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.

(机翻:每个输入文件包含一个测试用例。每一种情况都以包含2个数字N和M(≤2000),N为学生总数,M为要检查的学生人数,第一行输入N,M,之后的N行,每一行包含一个6位数字组成的学生ID,然后是该学生的三个整数成绩(范围是[0,100]),顺序是C,M,E, 然后是M行,每一行包含一个学生号。)

输出格式
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".

(为M的每一个学生,在一行中打印出他/她的最好的排名,和符号

对应的秩,用空格隔开。

排序方法的优先级按A> C> M >排序

一个学生有更多的方法来获得同样的最佳排名,输出一个最优先级最高的。

如果学生不在评分名单上,只需输出“N/ a”)

输入样例

56
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

输出样例:

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

题意:
现已知n个考生的3门课分数C、M、E,而平均分数A可以由这3个分数得到。现在
分别按这4个分数对n个考生从高到低排序,这样对每个考生来说,就会有4个排名且每个
分数都会有一个排名。接下来会有m个查询,每个查询输入一个考生的ID,输出该考生4
个排名中最高的那个排名及对应是A、C、M、E中的哪一个。如果对不同课程有相同排名的
情况,则按优先级A>C>M>E输出;如果查询的考生ID不存在,则输出N/A。
样例解释

studentID C M E A highestrank
310101 98(1) 85(5) 88(4) 90(2) 1C
310102 70(5) 95(1) 88(4) 84(5) 1M
310103 82(4) 87(4) 941() 88(3) 1E
310104 91(2) 91(2) 91(2) 91(1) 1A
310105 85(3) 90(3) 90(3)

88(3)

3A


思路:
步骤1:考虑到优先级为A>C>M>E,不妨在设置数组时就按这个顺序分配序号为0、
3的元素,即0对应A、1对应C、2对应M及3对应E。
以结构体类型Shudeont存放6位整数的ID和4个分数(grade[0]~grade[3]分别代表A、C、
M、E)。
由于ID是6位的整数,因此不妨设置Rank[1000000][4]数组,其中Rank[id][0]~Rank[id][3]
表示编号为ID的考生的4个分数各自在所有考生中的排名。
步骤2:读入考生的ID和3个分数,同时计算平均分A。
按顺序枚举A、C、M、E,对每个分数,将所有考生排序,并在Rank数组中记录排名。
在查询时,对读入的查询D,先看其是否存在(可通过Rank[id]的初值做判定)。如果存
在,选出Rank[id][0]~Rank[id][3]中数字最小(即排名最高)的那个即可。
时间复杂度为O(nlogn)。
注意点:
①要注意优先级顺序是A>C>M>E,所以为了方便枚举,在设置数组时尽量把A放
在C、M、E前面。
排名时,相同分数算作排名相同,所以91、90、88、88、84的排名应该算作1、2、
3、3、5。在具体实现时,切记不要算作1、2、3、3、4,否则中间3个测试点至少会错一个。
③ID是整数,不会是字符型。
四舍五入。但本题采用向下取整的方式也能通过,或者采用更简洁的方式一—不取平均,直
④本题没有明示平均分是否需要取整以及取整方式,根据题目描述中的例子可以看出是
接存储三门课的总分。
参考代码:
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
struct Student {
    int grade[4];//分别记录A,C,M,M四门的成绩。
    int id;
}stu[2010];//建立一个Student结构体
char course[4] = {'A','C','M','E'};
int n, m,now;
int Rank[10000][4] = { 0 };//*
bool cmp(Student a, Student b) {
    return a.grade[now] > b.grade[now];//分高的在前面
}
int main() {
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; i++) {
        scanf("%d%d%d%d", &stu[i].id, &stu[i].grade[1], &stu[i].grade[2], &stu[i].grade[3]);
        stu[i].grade[0] = round((stu[i].grade[1] + stu[i].grade[2] + stu[i].grade[3])/3.0);//利用round函数求平均值(四舍五入)。
    }
    for (now = 0; now < 4; now++) {//枚举A,C,M,E科
        sort(stu, stu + n, cmp);//分数从大到小排序
        Rank[stu[0].id][now] = 1;//先将分数最高的考生的此科排名设为1;
        for (int j = 1; j < n; j++) {
            if (stu[j].grade[now] == stu[j - 1].grade[now]) {
                Rank[stu[j].id][now] = Rank[stu[j - 1].id][now];//与上一个学生的分数相同
            }
            else {
                Rank[stu[j].id][now] = j + 1;//分数不同时
            }
            }
        }
    int search;//要查询的考生id
    for(int i=0;i<m;i++){
        scanf("%d", &search);
        if (Rank[search][0] == 0) {
            printf("N/A\n");
        }
        else {
            int k=0;
            for (int j = 0; j < 4; j++) {
                if (Rank[search][j] < Rank[search][k]) {
                    k = j;//找到四科里面排名最靠前的,输出
                }
            }
            printf("%d %c\n",Rank[search][k],course[k]);
        }
    }
    return 0;
}

posted @ 2021-04-28 16:37  银发制御  阅读(95)  评论(0)    收藏  举报