7-41 PAT排名汇总 (25 分)

计算机程序设计能力考试(Programming Ability Test,简称PAT)旨在通过统一组织的在线考试及自动评测方法客观地评判考生的算法设计与程序设计实现能力,科学的评价计算机程序设计人才,为企业选拔人才提供参考标准(网址http://www.patest.cn)。

每次考试会在若干个不同的考点同时举行,每个考点用局域网,产生本考点的成绩。考试结束后,各个考点的成绩将即刻汇总成一张总的排名表。

现在就请你写一个程序自动归并各个考点的成绩并生成总排名表。

输入格式:
输入的第一行给出一个正整数N(≤100),代表考点总数。随后给出N个考点的成绩,格式为:首先一行给出正整数K(≤300),代表该考点的考生总数;随后K行,每行给出1个考生的信息,包括考号(由13位整数字组成)和得分(为[0,100]区间内的整数),中间用空格分隔。

输出格式:
首先在第一行里输出考生总数。随后输出汇总的排名表,每个考生的信息占一行,顺序为:考号、最终排名、考点编号、在该考点的排名。其中考点按输入给出的顺序从1到N编号。考生的输出须按最终排名的非递减顺序输出,获得相同分数的考生应有相同名次,并按考号的递增顺序输出。

输入样例:
2
5
1234567890001 95
1234567890005 100
1234567890003 95
1234567890002 77
1234567890004 85
4
1234567890013 65
1234567890011 25
1234567890014 100
1234567890012 85
输出样例:
9
1234567890005 1 1 1
1234567890014 1 2 1
1234567890001 3 1 2
1234567890003 3 1 2
1234567890004 5 1 4
1234567890012 5 2 2
1234567890002 7 1 5
1234567890013 8 2 3
1234567890011 9 2 4

解答:注意题目:考生的输出须按最终排名的非递减顺序输出,获得相同分数的考生应有相同名次,并按考号的递增顺序输出

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 40000

typedef struct{
    char Id[15];
    int winTotal;
    int TestRoom;
    int winRoom;
    int Score;
} Student;

Student student[MAX];

typedef struct{
    char Id[15];
    int Score;
    int win;
} LocalStudent;

LocalStudent l_student[MAX];

int totalPos=0;

int cmp_local_student(const void *a,const void *b);
int getMid(int left,int right);
void _sort(int left, int right);
int rightJudge(Student a,Student b);
int leftJudge(Student a,Student b);

int main(){
    int n,k,end;
    scanf("%d",&n);
    for(int i=0; i<n; i++){
        scanf("%d",&k);
        for(int j=0; j<k; j++){
            scanf("%s %d",l_student[j].Id,&l_student[j].Score);
        }
        qsort(l_student,k,sizeof(LocalStudent),cmp_local_student);
        l_student[0].win=1;
        for(int j=1; j<k; j++){
            if(l_student[j].Score==l_student[j-1].Score){
                l_student[j].win=l_student[j-1].win;
            }else{
                l_student[j].win=j+1;
            }
        }
        end=totalPos+k;
        for(int j=0; totalPos<end; totalPos++,j++){
            strcpy(student[totalPos].Id,l_student[j].Id);
            student[totalPos].TestRoom=i+1;
            student[totalPos].winRoom=l_student[j].win;
            student[totalPos].Score=l_student[j].Score;
        }
    }
    _sort(0,totalPos-1);
    student[0].winTotal=1;
    for(int i=1; i<totalPos; i++){
        if(student[i].Score==student[i-1].Score){
            student[i].winTotal=student[i-1].winTotal;
        }else{
            student[i].winTotal=i+1;
        }
    }
    printf("%d\n",totalPos);
    for(int i=0; i<totalPos; i++){
        printf("%s %d %d %d\n",student[i].Id,student[i].winTotal,student[i].TestRoom,student[i].winRoom);
    }
    return 0;
}

int cmp_local_student(const void *a,const void *b){
    int res=((LocalStudent*)a)->Score - ((LocalStudent*)b)->Score;
    if(res == 0){
        res=strcmp(((LocalStudent*)a)->Id, ((LocalStudent*)b)->Id);
        if(res>0){
            return 1;
        }else{
            return 0;
        }
    }else if(res<0){
        return 1;
    }else{
        return 0;
    }
}

void _sort(int left, int right){
    if(left<right){
        int middle=getMid(left,right);
        _sort(left,middle);
        _sort(middle+1,right);
    }
}

int getMid(int left,int right){
    Student temp=student[left];
    while(left<right){
        while(left<right && rightJudge(student[right],temp)){
            right--;
        }
        student[left]=student[right];
        while(left<right && leftJudge(student[left],temp)){
            left++;
        }
        student[right]=student[left];
    }
    student[left]=temp;
    return left;
}

int rightJudge(Student a,Student b){
    int res=b.Score-a.Score;
    if(res==0){
        res=strcmp(b.Id, a.Id);
        if(res>0){
            return 0;
        }else{
            return 1;
        }
    }else if(res>0){
        return 1;
    }else{
        return 0;
    }
}

int leftJudge(Student a,Student b){
    int res=a.Score-b.Score;
    if(res==0){
        res=strcmp(a.Id, b.Id);
        if(res>0){
            return 0;
        }else{
            return 1;
        }
    }else if(res>0){
        return 1;
    }else{
        return 0;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值