PAT-A1025 PAT Ranking

这是一道非常基础的排序题,不过在结构体下显得有点麻烦。
我们先来看题目:

Programming Ability Test (PAT) is organized by the College of Computer Science and Technology of Zhejiang University. Each test is supposed to run simultaneously in several places, and the ranklists will be merged immediately after the test. Now it is your job to write a program to correctly merge all the ranklists and generate the final rank.

Input Specification:
Each input file contains one test case. For each case, the first line contains a positive number N (≤100), the number of test locations. Then N ranklists follow, each starts with a line containing a positive integer K (≤300), the number of testees, and then K lines containing the registration number (a 13-digit number) and the total score of each testee. All the numbers in a line are separated by a space.

Output Specification:
For each test case, first print in one line the total number of testees. Then print the final ranklist in the following format:

registration_number final_rank location_number local_rank
The locations are numbered from 1 to N. The output must be sorted in nondecreasing order of the final ranks. The testees with the same score must have the same rank, and the output must be sorted in nondecreasing order of their registration numbers.

原文大意就是,先输入一个正整数n,代表考场数,再输入n组数据,每组数据包括:
正整数k,代表该考场的考生数;
k组考生数据,分别是考生的id(13位数字)和考生的成绩。
现在要求你对每个考场的考生按成绩从高到低排名,如果分数相同,则按学号从低到高排;然后再对所有考生进行排名,排名规则同上。
输出数据格式为,先输出考生总人数,再依次输出每个考生的id、总排名,考场号,在其考场的排名。

大体思路:

对结构体中的元素进行排序很容易实现,这里着重讲解一下如何处理两个考生分数相同的情况:
如果两个考生分数相同,那么他们输出时虽然按准考证号决定输出顺序,但他们的排名必须是相同的,并且后面的同学的排名必须进行特殊变动。举个例子:

小A、小B和小C的成绩分别为90、90、7分,那么小A和小B都是第1名,且小C是第三名,而不是第二名。难点就在于如何计算出小C的排名。

这里给出一个思路,即,先将该考生数列进行排序,排序后,将第一个考生设置为第一名,然后从第二个考生开始,进行分支判定,如果这个考生的成绩和前一个考生相等,那么该考生的排名也和前一个考生相等,否则该考生的成绩就等于它数组下标+1。

清楚了这一点后,这个问题就迎刃而解了。下面是AC代码:

#include <bits/stdc++.h>
using namespace std;
struct student{
    char name[20];
    int kc_rank;
    int score;
    int location_num;
}stu[30015];
bool cmp(student a,student b)
{
     if(a.score!=b.score)return a.score>b.score;
     else return strcmp(a.name,b.name)<0;//注意这里cmp函数编写方法
}
int main(){
    int k,n,i,j,num=0;//n代表考场数,k代表每个考场的人数,num代表考生总人数
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&k);
        for(j=1;j<=k;j++)
        {
            scanf("%s",stu[num].name);
            scanf("%d",&stu[num].score);
            stu[num].location_num=i;
            num++;
        }
        sort(stu+num-k,stu+num,cmp);//对每个考场的考生排序
        stu[num-k].kc_rank=1;
        for(j=num-k+1;j<num;j++)//处理分数相同的情况
        {
            if(stu[j].score==stu[j-1].score)
                stu[j].kc_rank=stu[j-1].kc_rank;
            else stu[j].kc_rank=j-num+k+1;
        }
    }
    sort(stu,stu+num,cmp);//对所有考生排序
    int r=1;
    printf("%d\n",num);
    for(i=0;i<num;i++)
        {
            printf("%s ",stu[i].name);
            if(i==0)printf("%d ",r);
            else
            {
                if(stu[i].score==stu[i-1].score)//同上,处理分数相同的情况
                    printf("%d ",r);
                else
                {
                    r=i+1;
                    printf("%d ",r);
                }
            }
            printf("%d ",stu[i].location_num);
            printf("%d\n",stu[i].kc_rank);
        }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值