【PAT甲级】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 CME 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 CM 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

题意分析

这题是每个学生都有自己的id,每个学生还有三种成绩和三种成绩的平均数,四种成绩都有各自的排名,然后给出学生id,求出学生这四种成绩排名中的最好排名并输出。

个人思路

这题考的是排序算法的应用。

我是建立了一个学生信息结构体,内部存着四种成绩和四种成绩排名。

通过四次排序对求出四个成绩排名并存入结构体中。

然后设立了一个map,映射着最后一次排序后的学生id和排序索引下标的映射。【目的是为了之后查找学生排名的时候能在O(logn)的时间内完成查询,加快查询速度】

有一个注意点:

99 98 98 97 96 这样的排名应该是1 2 2 4 5,相同的成绩同排名,之后的排名会增加到当前人数。

代码实现

#include <cstdio>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <vector>
#include <cmath>
#include <algorithm>
#include <iostream>
#define ll long long
#define eps 1e-8
#define INF 0x7FFFFFFF

const int maxn = 2005;

using namespace std;

// 学生结构体
struct Student {
    string id;
    int c_score, m_score, e_score;
    double a_score;
    int c_rank, m_rank, e_rank, a_rank;
};
Student students[maxn];

// 四个成绩的比较函数
bool cmp_c(Student s1, Student s2) {
    return s1.c_score > s2.c_score;
}

bool cmp_m(Student s1, Student s2) {
    return s1.m_score > s2.m_score;
}

bool cmp_e(Student s1, Student s2) {
    return s1.e_score > s2.e_score;
}

bool cmp_a(Student s1, Student s2) {
    return s1.a_score > s2.a_score;
}

// 找到某个学生的最佳排名和排名类型
void find_biggest_rank(Student s, int & rank, char & type) {
    if (s.e_rank <= rank) {
        rank = s.e_rank;
        type = 'E';
    }
    if (s.m_rank <= rank) {
        rank = s.m_rank;
        type = 'M';
    }
    if (s.c_rank <= rank) {
        rank = s.c_rank;
        type = 'C';
    }
    if (s.a_rank <= rank) {
        rank = s.a_rank;
        type = 'A';
    }
}

int main() {
    // 输入
    int n, m;
    cin >> n >> m;
    // 输入学生成绩并求出平均成绩
    for (int i = 0; i < n; i ++) {
        cin >> students[i].id >> students[i].c_score >> students[i].m_score >> students[i].e_score;
        students[i].a_score = 1.0 * (students[i].c_score+students[i].m_score+students[i].e_score) / 3;
    }
    // 求出c语言排名
    sort(students, students+n, cmp_c);
    students[0].c_rank = 1;
    for (int i = 1; i < n; i ++) {
        if (students[i].c_score == students[i-1].c_score) students[i].c_rank = students[i-1].c_rank;
        else students[i].c_rank = i + 1;
    }
    // 求出数学排名
    sort(students, students+n, cmp_m);
    students[0].m_rank = 1;
    for (int i = 1; i < n; i ++) {
        if (students[i].m_score == students[i-1].m_score) students[i].m_rank = students[i-1].m_rank;
        else students[i].m_rank = i + 1;
    }
    // 求出英语排名
    sort(students, students+n, cmp_e);
    students[0].e_rank = 1;
    for (int i = 1; i < n; i ++) {
        if (students[i].e_score == students[i-1].e_score) students[i].e_rank = students[i-1].e_rank;
        else students[i].e_rank = i + 1;
    }
    // 求出平均成绩排名
    sort(students, students+n, cmp_a);
    students[0].a_rank = 1;
    for (int i = 1; i < n; i ++) {
        if (students[i].a_score == students[i-1].a_score) students[i].a_rank = students[i-1].a_rank;
        else students[i].a_rank = i + 1;
    }
    // 建立字符串到平均成绩排序的映射
    map <string, int> idx;
    for (int i = 0; i < n; i ++) {
        idx[students[i].id] = i+1;
    }
    // 查找m个学生成绩
    while (m --) {
        string id;
        cin >> id;
        if (idx[id] == 0) {
            cout << "N/A" << endl;
        }
        else {
            int pos = idx[id]-1;
            int rank = INF;
            char type = '0';
            find_biggest_rank(students[pos], rank, type);
            cout << rank << " " << type << endl;
        }
    }
    return 0;
}

总结

学习不息,继续加油

感觉这题的代码写得又臭又长,中间还因为粗心一个细节没注意到找了好久,希望之后能找到比较简洁明了的代码学习一下。

猜你喜欢

转载自blog.csdn.net/qq_34586921/article/details/83548802