PAT甲级1012 The Best Rank (25 分)
- 题意:给出n个学生的学号(六位数),语文数学英语三门成绩,对排名进行查找。输入查找的学号,输出该同学最好的科目(语文,数学,英语,平均分)成绩的排名及对应科目,若两门课排名相同则按平均分语数英的优先级输出优先级最高的排名及科目。找不到此学生则输出“N/A”。
- 思路:
- step1:建立学生信息结构体,包含学号,语数英及平均成绩,语数英及平均成绩排名数组(数组按E,M,C,A顺序),满足题意的优先级最高的科目。
- step2:输入学生信息,并计算平均分。
- step3:求语数英及平均成绩分别对应的排名(以1 1 3 4 5)方式存储
- step4:遍历n名学生,用exist[1000000]数组标记学生(学号即为下标),同时给best赋值,排名更高的在前面或排名相同优先级高的在前面(这里就要注意了,我们再结构体中声明数组的时候的顺序刚好是优先级顺序)
- step5:输出(巧妙地运用了exist数组)
#include <bits/stdc++.h>
using namespace std;
struct node
{
int id,best;
int rank[5];//0-E,1-M,2-C,3-A;
int grade[5];//同上
}stu[2021];
char str[4]={'E','M','C','A'};//用于最后对应科目的输出
int flag;//flag是全局变量,这里可以通过flag由0→3分别进行四科的排序
int exist[1000000]={0};//标记id,这里很巧妙,以下的代码中再解释
bool cmp(node a,node b)//对成绩进行排序
{
return a.grade[flag]>b.grade[flag];
}
int main()
{
int n,m;
int id;
int temp;
cin>>n>>m;
for(int i=0;i<n;i++)
{
scanf("%d%d%d%d",&stu[i].id,&stu[i].grade[2],&stu[i].grade[1],&stu[i].grade[0]);
stu[i].grade[3]=(stu[i].grade[2]+stu[i].grade[1]+stu[i].grade[0])/3+0.5;
}
for( flag=0;flag<4;flag++)
{
sort(stu,stu+n,cmp);
stu[0].rank[flag]=1;//第一名的rank标记为1
for(int j=1;j<n;j++)
{
stu[j].rank[flag]=j+1;//如果这名同学与上一名同学此科目得分相同,则有相同的排名,这个排名赋值还是很巧妙的
if(stu[j].grade[flag]==stu[j-1].grade[flag])
stu[j].rank[flag]=stu[j-1].rank[flag];
}
}
for(int i=0;i<n;i++)
{
exist[stu[i].id]=i+1;
stu[i].best=0;
for(int j=1;j<4;j++)//求得排名最好的科目,这里注意到优先级关系,即使两个科目排名相同时,按照数组声明时的对应关系,一次循环总是可以得到优先级最高的排名
{
if(stu[i].rank[j]<=stu[i].rank[stu[i].best])
{
stu[i].best=j;
}
}
}
while(m--)
{
cin>>id;
temp=exist[id];//这里就是学号与输入的对应了,上文中exist[stu[i].id]=i+1就是将学号转化为了输入的顺序,第几个输入下标就是几-1,在接下来对应输出即可,这里真的好巧秒!!!
if(temp==0)
printf("N/A\n");
else
{
printf("%d %c\n",stu[temp-1].rank[stu[temp-1].best],str[stu[temp-1].best]);//输出,完结撒花!!!
}
}
return 0;
}