题目链接:PAT 1025 PAT Ranking
1、相关结构体的定义
struct Student
{
char id[15]; //准考证号
int score; //分数
int location_number; //考场号
int local_rank; //考场内排名
}stu[30010];
2、cmp函数的编写
要求:
(1)如果两个学生分数不相同,那么分数高的排在前面。
(2)否则,将姓名字典序小的排在前面。
bool cmp(Student a, Student b)
{
if(a.score != b.score)
return a.score>b.score;
else
return strcmp(a.id, b.id) < 0;
}
3、排名的实现
很多排序题都会要求在排序之后计算出每个个体的排名,并且规则一般是:分数不同的排名不同,分数相同的排名相同但占用一个排位。
对这种要求,一般都需要在结构体类型定义时就把排名这项加到结构体中(正如上文中Student类型的定义一样)。 于是在数组排序完成后就有下面两种方法来实现排名的计算:
(1)先将数组第一个个体(假设数组下标从0开始)的排名记为1,然后遍历剩余个体:如果当前个体的分数等于上一个个体的分数,那么当前个体的排名等于上个个体的排名;否则,当前个体的排名等于数组下标加1。
stu[0].r = 1;
for(int i=1;i<n;i++)
{
if(stu[i].score == stu[i-1].score)
stu[i].r = stu[i-1].r;
else
stu[i].r = i+1;
}
(2)而有时题目中不一定需要真的把排名记录下来,而是直接输出即可,那么也可以用这样的办法;令int 型变量 r 初值为1,然后遍历所有个体:如果当前个体不是第一一个个体且当前个体的分数不等于上一个个体的分数,那么令 r 等于数组下标加1,这时 r 就是当前个体的排名,直接输出即可。这样的做法适用于需要输出的信息过多,导致第一种方法代码冗长的情况。
int r = 1;
for(int i=0;i<n;i++)
{
if(i>0 && stu[i].score != stu[i-1].score)
r = i+1;
//输出当前个体信息,或者令stu[i].r = r也行
}
4、注意点:
对同一考场的考生单独排序的方法:定义 int 型变量num,用来存放当前获取到的考生人数。每读入一个考生的信息,就让 num 自增。这样当读取完一个考场的考生信息(假设该考场有k个考生)后,这个考场的考生所对应的数组下标便为区间 [num - k, num)。
AC代码:
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
struct Student
{
char id[15]; //准考证号
int score; //分数
int location_number; //考场号
int local_rank; //考场内排名
}stu[30010];
bool cmp(Student a, Student b)
{
if(a.score != b.score)
return a.score>b.score;
else
return strcmp(a.id, b.id) < 0;
}
int main()
{
int num = 0; //记录总考生数
int n,k;
scanf("%d",&n); //考场数
for(int i=1;i<=n;i++)
{
scanf("%d",&k); //该考场内人数
for(int j=0;j<k;j++)
{
scanf("%s %d", stu[num].id, &stu[num].score);
stu[num].location_number = i; //该考生的考场号为i
num++; //总考生数+1
}
sort(stu+num-k, stu+num, cmp); //将该考场的考生排序
stu[num-k].local_rank = 1; //该考场第一名的local_rank记为1
for(int j=num-k+1;j<num;j++)
{
if(stu[j].score == stu[j-1].score) //如果与前一位考生同分,local_rank也相同
stu[j].local_rank = stu[j-1].local_rank;
else //如果不同分,local_rank为该考生前的人数
stu[j].local_rank = j+1-(num-k);
}
}
printf("%d\n",num);
sort(stu, stu+num, cmp); //将所有考生排序
int r = 1;
for(int i=0;i<num;i++)
{
if(i>0 && stu[i].score != stu[i-1].score)
r = i+1;
printf("%s ",stu[i].id);
printf("%d %d %d\n", r, stu[i].location_number, stu[i].local_rank);
}
return 0;
}