1. 程式人生 > >1085. PAT單位排行 (25) PAT乙級真題

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));
        }
    }
}