PAT Advanced 1012. The Best Rank (25) (C語言實現(xiàn))

我的PAT系列文章更新重心已移至Github,歡迎來看PAT題解的小伙伴請到Github Pages瀏覽最新內(nèi)容。此處文章目前已更新至與Github Pages同步。歡迎star我的repo

題目

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 ( \le 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

思路

計算排名的方法:

很多人用的結(jié)構(gòu)體排序,這樣是比較耗時的(尤其是基數(shù)很大的時候)。

我的方法是在讀取學(xué)生成績的時候順便記錄0~100分各有多少人,然后根據(jù)得分人數(shù)計算排名。舉個例子:

  • 如果100分有1人,99分有2人,98分有3人,97分有4人。

那么

  • 得100分的排名是1,得99分的排名是2(并列),98分的排名是4(并列),97分的排名是7(并列)。

規(guī)律是什么?如果學(xué)生獲得的分數(shù)分別有a1>a2>a3>...>ai>...,那么

  • 分數(shù)a[i]的名次 = 分數(shù)a[i-1]的名次 + 分數(shù)a[i-1]的人數(shù)
  • 分數(shù)a[1]的名次 = 1

這其實是遞歸定義,如果定義一個不存在的高分a0(比如101分)人數(shù)=1(代碼中一開始的初始化就是做這個),那么上面的關(guān)系就簡化成了

  • 分數(shù)a[i]的名次 = a[0]~a[i-1]的人數(shù)總和,(i>0)

可以驗證一下:97分的排名=98~101分人數(shù)總和=3+2+1+1=7

平均分計算方法:

仔細看題目中給的例子,平均分是四舍五入的,不過我試過在算平均分的時候直接3個數(shù)相加除以3,還是能AC。所以要不是題目沒有設(shè)置這樣的測試點,要不就是題目認為兩種算法結(jié)果都正確。

代碼

最新代碼@github,歡迎交流

#include <stdio.h>

typedef struct Student{ int ID, score[4]; } Student;

int main()
{
    /* scores array stores the number of students of any score */
    int N, M, ID, scores[4][102] = {{0}};

    /* Setting a score of 101 is to make it easy to calculate rank */
    scores[0][101] = scores[1][101] = scores[2][101] = scores[3][101] = 1;
    Student students[2000];

    scanf("%d %d", &N, &M);
    for(int i = 0; i < N; i++)
    {   /* record all the scores for every student: A, C, M, E */
        Student *s = students + i;
        scanf("%d %d %d %d", &s->ID, &s->score[1], &s->score[2], &s->score[3]);
        s->score[0] = (s->score[1] + s->score[2] + s->score[3] + 1) / 3;
        for(int j = 0; j < 4; j++)                         /* +1 for rounding */
            scores[j][s->score[j]]++;       /* record how many got this score */
    }

    for(int i = 0; i < M; i++)
    {
        int max = 3, ranks[4] = {0}, stu;

        scanf("%d", &ID);
        for(stu = 0; stu < N && students[stu].ID != ID; stu++) ;      /* find */
        if(stu == N) { puts("N/A"); continue;}

        for(int j = 3; j >= 0; j--)
        {   /* calculate the rank: sum the counts from score + 1 to 101 */
            /* e.g. score 100 will have rank 1, since scores[101] is 1 */
            for(int score = 100; score >= students[stu].score[j]; score--)
                ranks[j] += scores[j][score + 1];
            if(ranks[j] <= ranks[max]) /* The best rank with highest priority */
                max = j;
        }
        printf("%d %c\n", ranks[max], "ACME"[max]);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • **2014真題Directions:Read the following text. Choose the be...
    又是夜半驚坐起閱讀 9,891評論 0 23
  • 周末,此刻,搭車返穗。車上思緒,發(fā)現(xiàn)自己的心態(tài)極不好,臉上冰冷無表情,對同事對家人均是這樣,感覺生活很無趣,沒有...
    QiuYyin閱讀 476評論 0 0
  • 【意康德】您身邊的滋補品專家,傳承千年養(yǎng)生智慧、倡導(dǎo)健康養(yǎng)生滋補,教您如何做養(yǎng)生達人?!簟铩艏用撕庙椖恐赂?,加盟好...
    可可靈精閱讀 837評論 4 0
  • 每次遠行 都會有些想念 每次離別 都會有些留戀 每次回家 都會有些改變 是窗臺蒙了塵 還是蘭花過了季 是掛歷卷了角...
    且行且夢113閱讀 191評論 0 2