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 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

题目大意:
就是一个排序的问题。

代码如下:

#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
    int id,best;        //存最高名次的下标, 像这种情况,从来都是比存值要来的更有效。
    int score[4],rank[4];
}stu[2001];
int flag=0;
bool cmp(node a,node b){ return a.score[flag]>b.score[flag];}
int main()
{
    int n,k,exist[1000000]={0},id;
    cin>>n>>k;
    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]);     // c   m    e     a
        stu[i].score[0]=(stu[i].score[1]+stu[i].score[2]+stu[i].score[3])/3+0.5;
    }
    for(int i=0;i<4;i++,flag++){         //flag为了控制排序的    名次排完了,并且存储好了
        sort(stu,stu+n,cmp);
        stu[0].rank[i]=1;
        for(int j=1;j<n;j++)              //这个地方得考虑名次相等的情况
            if(stu[j].score[i]==stu[j-1].score[i]) stu[j].rank[i]=stu[j-1].rank[i];
            else stu[j].rank[i]=j+1;
    }
    for(int i=0;i<n;i++){               //为了寻找best,找到最高名次的小标
        int min=n+1;
        exist[stu[i].id]=i+1;            //这个时候stu数组中的顺序已经确定了,只是为了以后方便定位
        for(int j=0;j<4;j++)
            if(stu[i].rank[j]<min){
                min=stu[i].rank[j];
                stu[i].best=j;
            }
    }
    char sub[4]={'A','C','M','E'};
    for(int i=0;i<k;i++){
        cin>>id;
        int t=exist[id];
        if(t) printf("%d %c\n",stu[t-1].rank[stu[t-1].best],sub[stu[t-1].best]);
        else printf("N/A\n");
    }
    /*for(int i=0;i<n;i++)
        printf("%d %d %d %d %d\n",stu[i].id,stu[i].score[0],stu[i].score[1],stu[i].score[2],stu[i].score[3]);
    for(int i=0;i<n;i++)
        printf("%d %d %d %d %d\n",stu[i].id,stu[i].rank[0],stu[i].rank[1],stu[i].rank[2],stu[i].rank[3]);*/
    return 0;
}

来总结一下:
正如图中的代码所示,代表了这道题写题的一个思路。接下来说一下思路,遇到的问题和感悟。

  • 思路就是:对每个成绩都排序,分别存储每个成绩的名词,在从所有名次中找到最高的名次,然后在输出最高名次的同时,也输出相对应的成绩。(思路很简单,关键在于如何存储,怎样定位!)

  • 首先,这个题这么多的成绩,声明好几个数组肯定是不合适的,而且还不好找,所以就需要定义一个结构体,(如果数量很少就可以使用下标的方法来存储)。既然有四个成绩,就要有四个下标,一一对应,来表示每个成绩的排名。best最有用的地方在于它找出的是最高名次的下标,这样就可以直接定位,而不用再费劲的去查找了。

  • sort函数中的自定义函数cmp中可以放置一个未知数flag,可以在循环中每次对同一类的成绩进行排序,但是flag必须为全局变量,要不然的话,会报错!
    !!! 排序的过程很关键,主要是因为排序是所有的一起换,而不是只换其中的某一项,所以可以放心大胆的换,也可以放心大胆的存储名次。

  • 最后就是exist数组设定,题目当中要求学号的长度为6位,我设置完1000000的长度之后,在我电脑上是运行不了的(估计是申请的空间太大了),所以可以在自己测试的时候,设置小一些,然后在提交的时候再改回去。这个数组的作用主要有两点:
    1)来查找这个id是否存在。
    2)也是最重要的一点,有了学生的id,因为要输出再去遍历结构体数组的话太麻烦了,这个数组就是将学生的id和这个id所在的结构体数组的下标结合在一起(方便在输出的时候直接定位)。

 exist[stu[i].id]=i+1;   

这个题难点不是在排序,而在于定位,定位的两个关键点,一个是best,一个是exist数组。

猜你喜欢

转载自blog.csdn.net/sun9979/article/details/86567074