1085. PAT单位排行 (25) PAT乙级真题

1085. PAT单位排行 (25)

每次 PAT 考试结束后,考试中心都会发布一个考生单位排行榜。本题就请你实现这个功能。

输入格式:

输入第一行给出一个正整数N(<=105),即考生人数。随后N行,每行按下列格式给出一个考生的信息:

准考证号 得分 学校

其中“准考证号”是由6个字符组成的字符串,其首字母表示考试的级别:“B”代表乙级,“A”代表甲级,“T”代表顶级;“得分”是 [0,100] 区间内的整数;“学校”是由不超过6个英文字母组成的单位码(大小写无关)。注意:题目保证每个考生的准考证号是不同的。

输出格式:

首先在一行中输出单位个数。随后按以下格式非降序输出单位的排行榜:

排名 学校 加权总分 考生人数

其中“排名”是该单位的排名(从1开始);“学校”是全部按小写字母输出的单位码;“加权总分”定义为“乙级总分/1.5 + 甲级总分 + 顶级总分*1.5”的整数部分;“考生人数”是该属于单位的考生的总人数。

学校首先按加权总分排行。如有并列,则应对应相同的排名,并按考生人数升序输出。如果仍然并列,则按单位码的字典序输出。

输入样例:
10
A57908 85 Au
B57908 54 LanX
A37487 60 au
T28374 67 CMU
T32486 24 hypu
A66734 92 cmu
B76378 71 AU
A47780 45 lanx
A72809 100 pku
A03274 45 hypu
输出样例:
5
1 cmu 192 2
1 au 192 3
3 pku 100 1
4 hypu 81 2
4 lanx 81 2

这道题最后3分的数据点真的折磨了我好久,尽管从柳神那里知道是关于数据精度的问题,但是柳神讲的模模糊糊的,我中间用了各种方法想要去解决精度问题都以失败而告终。最后又回去审题。

吃过1080的亏,这次我直接用空间去换时间,并没有出现超时的情况。我先把所有学生读进来并计算分数,在本题中除了"A","T","B"有用,后面的准考证号属于无用信息,可以只读最前面一个字符,把后面的扔掉不要。然后根据学校先进行一个排序,再进行分数的累加(这使分数的累加更加轻松)。为了防止一个人“屠校”的情况发生,将累加过后的学生个人成绩标记为-1,只保留该校的总成绩(题目中给的信息让我认为有的学校可能总分为0)。在每个学校的分数累加完成后直接将分数取整数部分(这是我解决精度问题的方法,虽然感觉像是卡了一个bug)。最后根据题目要求排个序输出就好了。下面是我的代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>


void input(int n);
int add(int n);
void output(int n);
int cmp(const void *a,const void *b);
int cmp1(const void *a,const void *b);


struct student
{
    char school[10];
    double score;
    int stu;
}student[100000];


int main(void)
{
    int n,a;
    scanf("%d%*c",&n);
    input(n);
    qsort(&student[0],n,sizeof(struct student),cmp);
    a=add(n);
    qsort(&student[0],n,sizeof(struct student),cmp1);
    output(a);
    return 0;
}

void input(int n)
{
    int i,j,score;
    char c;
    for (i=0;i<n;i++)
    {
        scanf("%c%*c%*c%*c%*c%*c%*c%d%*c",&c,&score);
        if (c=='B') student[i].score=score/1.5;
        else if (c=='T') student[i].score=score*1.5;
        else student[i].score=score*1.0;
        j=0;
        do
        {
            scanf("%c",&student[i].school[j]);
            if (student[i].school[j]>='A' && student[i].school[j]<='Z') student[i].school[j]=student[i].school[j]-'A'+'a';
        }while(student[i].school[j++]!='\n');
        student[i].school[--j]='\0';
    }
}

void output(int n)
{
    int i,j,a;
    printf("%d\n",n);
    for (i=0;i<n;i++)
    {
        j=i;a=(int)student[i].score;
        while(j<n && (int)student[j].score==a)
        {
            printf("%d %s %d %d\n",i+1,student[j].school,(int)student[j].score,student[j].stu);
            j++;
        }
        i=j-1;
    }
}

int add(int n)
{
    int i,j,s=0;
    for (i=0;i<n;i++)
    {
        j=i+1;student[i].stu=1;
        while(strcmp(student[i].school,student[j].school)==0)
        {
            student[i].score+=student[j].score;
            student[j].score=-1;s++;                //防止出现某人分数比别的整个学校总分还高的情况
            student[i].stu++;j++;
        }
        student[i].score=(int)student[i].score;
        i=j-1;
    }
    return n-s;
}

int cmp(const void *a,const void *b)
{
    struct student *aa=(struct student *)a;
    struct student *bb=(struct student *)b;
    return (strcmp(aa->school,bb->school));
}

int cmp1(const void *a,const void *b)
{
    struct student *aa=(struct student *)a;
    struct student *bb=(struct student *)b;
    if (aa->score != bb->score)
    {
        return (aa->score < bb->score ? 1:-1);
    }
    else
    {
        if (aa->stu != bb->stu )
        {
            return (aa->stu > bb->stu ? 1:-1);
        }
        else
        {
            return (strcmp(aa->school,bb->school));
        }
    }
}



  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值