计算机程序设计能力考试(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
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
解题思路:
思路比较好想,创建一个包含 考号、成绩、最终排名、考点编号、在该考点的排名的结构。在输入每个考场的数据时,顺便将考场号输入。然后对这一组进行考场内排名编号,随后插入到总体数据的尾端。最后对总体数据进行排序编号。
问题较大就出现在算法时间效率不过关,最开始我自己写的快排,但是不会在快排里改相同编号小号在前的比较方式,于是就用了C语言自带的qsort函数,就简单了好多。
关于qsort函数,做一个简要的介绍:
格式:qsort(需要比较数据区域的地址,数据的长度,数据中每个结点需要的字节,比较函数)
比较函数:int cmp(const void* a, const void* b) ,返回值>0说明a>b, 返回值<0说明a<b, 返回值>0说明a=b。const void* 可以把a、b转换成需要的指针类型。蓝色字体代表可以自己更改。
1.对比函数,就按照这个模式套。
//对比函数
int Compare(const void* a, const void* b)
{
People* pa = (People*)a;
People* pb = (People*)b;
if(pa->grade != pb->grade)
{
return pb->grade - pa->grade;
}
else
{
return strcmp(pa->num, pb->num);
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define bool char
#define true 1
#define false 0
#define MaxSize 30005 //按照题意的要求300*100这么大的空间
//每个人的结点类型
typedef struct People
{
char num[14]; //学号
int grade; //成绩
int finally; //最终成绩
int place; //考点编号
int kdpm; //考点排名
} People;
//总体的类型
typedef struct Peoples
{
People *data;
int length;
}Peoples;
//初始化
bool InitPeoples(Peoples* test)
{
test->data = (People*)malloc(sizeof(People)*MaxSize);
test->length = 0;
return true;
}
//遍历输出
bool PrintPeoples(Peoples test)
{
for(int i = 0; i < test.length; i++)
{
printf("%s %d %d %d\n", test.data[i].num,
test.data[i].finally,test.data[i].place, test.data[i].kdpm);
}
return true;
}
//对比函数
int Compare(const void* a, const void* b)
{
People* pa = (People*)a;
People* pb = (People*)b;
if(pa->grade != pb->grade)
{
return pb->grade - pa->grade;
}
else
{
return strcmp(pa->num, pb->num);
}
}
//组内排序
bool Insort(Peoples* test)
{
int i;
//先按照题意要求排好序
qsort(test->data, test->length, sizeof(People), Compare);
for(i = 0; i < test->length; i++)
{
//输入考点排名,成绩相同者排名相同
if(i == 0 || test->data[i].grade != test->data[i-1].grade)
test->data[i].kdpm = i+1;
else
test->data[i].kdpm = test->data[i-1].kdpm;
}
return true;
}
//总体排序
bool AllSort(Peoples* test)
{
int i;
//按照成绩从大到小排序
qsort(test->data, test->length, sizeof(People), Compare);
for(i = 0; i < test->length; i++)
{
//输入考点排名,成绩相同者排名相同
if(i == 0 || test->data[i].grade != test->data[i-1].grade)
test->data[i].finally = i+1;
else
test->data[i].finally = test->data[i-1].finally;
}
//成绩相同,学号小的排上边
return true;
}
//输入一组数据, 排序后插入底部
bool InPut(Peoples* test, int n) //n用来标记考点编号
{
int i;
int k; //每个考点的人数
scanf("%d",&k);
//创建一个用来临时存放每个考点的结构
Peoples test1;
test1.data = (People*)malloc(sizeof(People)*(k+1));
test1.length = 0;
//InitPeoples(&test1);
//学号、成绩和考点输入
for(i = 0; i < k; i++)
{
scanf("%s %d", test1.data[i].num, &test1.data[i].grade);
test1.data[i].place = n;
test1.length++;
}
//进行考点内排名,考点排名输入完毕
Insort(&test1);
//将每一组接在整体尾部
for(i = test->length; i < test->length+test1.length; i++)
{
test->data[i] = test1.data[i-test->length];
}
test->length += test1.length;
return true;
}
int main()
{
Peoples test;
InitPeoples(&test);
int n, i;
scanf("%d", &n);
for(i = 1; i <= n; i++)
{
InPut(&test, i);
}
AllSort(&test);
//printf("\n");
printf("%d\n",test.length);
PrintPeoples(test);
return 0;
}