1095 解码PAT准考证 (25分)
PAT 准考证号由 4 部分组成:
·第 1 位是级别,即 T 代表顶级;A 代表甲级;B 代表乙级;
·第 2~4 位是考场编号,范围从 101 到 999;
·第 5~10 位是考试日期,格式为年、月、日顺次各占 2 位;
·最后 11~13 位是考生编号,范围从 000 到 999。
现给定一系列考生的准考证号和他们的成绩,请你按照要求输出各种统计信息。
输入格式:
输 入 首 先 在 一 行 中 给 出 两 个 正 整 数 N ( ≤ 1 0 4 ) 输入首先在一行中给出两个正整数 N(≤10^{4} ) 输入首先在一行中给出两个正整数N(≤104)和 M(≤100),分别为考生人数和统计要求的个数。
接下来 N 行,每行给出一个考生的准考证号和其分数(在区间 [0,100] 内的整数),其间以空格分隔。
考生信息之后,再给出 M 行,每行给出一个统计要求,格式为:类型 指令,其中
·类型 为 1 表示要求按分数非升序输出某个指定级别的考生的成绩,对应的 指令 则给出代表指定级别的字母;
·类型 为 2 表示要求将某指定考场的考生人数和总分统计输出,对应的 指令 则给出指定考场的编号;
·类型 为 3 表示要求将某指定日期的考生人数分考场统计输出,对应的 指令 则给出指定日期,格式与准考证上日期相同。
输出格式:
对每项统计要求,首先在一行中输出 Case #: 要求,其中 # 是该项要求的编号,从 1 开始;要求 即复制输入给出的要求。随后输出相应的统计结果:
·类型 为 1 的指令,输出格式与输入的考生信息格式相同,即 准考证号 成绩。对于分数并列的考生,按其准考证号的字典序递增输出(题目保证无重复准考证号);
·类型 为 2 的指令,按 人数 总分 的格式输出;
·类型 为 3 的指令,输出按人数非递增顺序,格式为 考场编号 总人数。若人数并列则按考场编号递增顺序输出。
如果查询结果为空,则输出 NA。
输入样例:
8 4
B123180908127 99
B102180908003 86
A112180318002 98
T107150310127 62
A107180908108 100
T123180908010 78
B112160918035 88
A107180908021 98
1 A
2 107
3 180908
2 999
输出样例:
Case 1: 1 A
A107180908108 100
A107180908021 98
A112180318002 98
Case 2: 2 107
3 260
Case 3: 3 180908
107 2
123 2
102 1
Case 4: 2 999
NA
这道题给我的感觉是遇到了一个“甲方”,提出的条件还挺多。我是用一个包含了各项信息的结构体来存储每个考生的信息的,然后将数据一分为三,分别针对三种case进行排序,然后按需查找。这样可以最大程度的降低每次查找还要排序的开销。case 3 比前两个要麻烦一点,在给出每次查找条件后要对每个考场的人数进行统计。我一开始为了逻辑统一,把考场编号从1开始,然而我用快排的时候是从0开始的,于是悲剧了,而且这个bug我用了好几个测试数据才测出来问题所在。这道题我在写完以后去看了一些做法,柳神写的cmp真的惊艳到我了,赶紧拿小本本出来学习。
虽然代码满分过了,时间也还过得去,但是现在发现还有不少改进的地方:case 2和case3其实没有必要排序的,被case 1带的惯性思维了,排序后的查找其实快不了多少,然而排序的时间确是实实在在的消耗了。下面我给的是便于阅读输出结果的使用文件输入输出代码,不用文件形式看结果会有点不好阅读。使用的时候在同目录下创建一个"1095.in"作为输入,会有一个“1095.out”作为输出文件,文本文档形式打开就好了。下面是代码:
#include
#include
typedef struct Stu
{
char level;
int exam_number;
long date;
int id_number;
int grade;
}Stu;
typedef struct Room
{
int Room_no;
int count;
}Room;
int cmp1(const void *a,const void *b);
int cmp2(const void *a,const void *b);
int cmp3(const void *a,const void *b);
int cmp4(const void *a,const void *b);
void case_1(char c,struct Stu student[4][10000],int n,FILE *q);
void case_2(struct Stu student[4][10000],int n,int exam,FILE *q);
void case_3(struct Stu student[4][10000],int n,long date,FILE *q);
int main(void)
{
FILE *p = fopen("./1095.in", "r");
FILE *q = fopen("./1095.out", "w");
Stu student[4][10000];
int n,m;
int i,j;
long temp,temp1,temp2;
char c;
fscanf(p,"%d %d%c",&n,&m,&c);
for(i = 0;i < n;i++)
{
fscanf(p,"%c",&c); //level
for(j = 1;j <= 3;j++)
{
student[j][i].level = c;
student[j][i].date = 0;
student[j][i].exam_number = 0;
student[j][i].grade = 0;
student[j][i].id_number = 0;
}
temp = 0;
for(j = 1;j <= 3;j++) //exam_number
{
fscanf(p,"%c",&c);
temp = temp * 10 + (c - '0');
}
temp1 = 0;
for(j = 1;j <= 6;j++) //date
{
fscanf(p,"%c",&c);
temp1 = temp1 * 10 + (c - '0');
}
temp2 = 0;
for(j = 1;j <= 3;j++) //id_number
{
fscanf(p,"%c",&c);
temp2 = temp2 * 10 + (c - '0');
student[j][i].date = temp1;
student[j][i].exam_number = temp;
}
fscanf(p,"%ld%c",&temp,&c);
for(j = 1;j <= 3;j++)
{
student[j][i].grade = temp;
student[j][i].id_number = temp2;
}
}
qsort(&student[1][0],n,sizeof(Stu),cmp1);
qsort(&student[2][0],n,sizeof(Stu),cmp2);
qsort(&student[3][0],n,sizeof(Stu),cmp3);
for(i = 1;i <= m;i++)
{
fprintf(q,"Case %d: ",i);
fscanf(p,"%ld",&temp);
if(temp == 1)
{
fscanf(p,"%c",&c);
fscanf(p,"%c",&c);
fprintf(q,"1 %c\n",c);
case_1(c,student,n,q);
}
else
{
if(temp == 2)
{
fscanf(p,"%ld",&temp);
fprintf(q,"2 %ld\n",temp);
case_2(student,n,temp,q);
}
else
{
fscanf(p,"%ld",&temp);
fprintf(q,"3 %06ld\n",temp);
case_3(student,n,temp,q);
}
}
if(i < m) fprintf(q,"\n");
}
fclose(p);
fclose(q);
return 0;
}
int cmp1(const void *a,const void *b)
{
struct Stu *aa=(Stu *)a;
struct Stu *bb=(Stu *)b;
int f = 1;
if(aa->level > bb->level)
{
f = 1;
}
else
{
if (aa->level < bb->level)
{
f = -1;
}
else //级别相同
{
if(aa -> grade < bb -> grade)
{
f = 1;
}
else
{
if(aa -> grade > bb -> grade)
{
f = -1;
}
else //成绩相等
{
if(aa -> exam_number > bb ->exam_number)
{
f = 1;
}
else
{
if(aa -> exam_number < bb ->exam_number)
{
f = -1;
}
else //同一考场
{
if(aa -> date > bb ->date)
{
f = 1;
}
else
{
if(aa -> date < bb ->date)
{
f = -1;
}
else //同一天
{
if(aa -> id_number > bb ->id_number)
{
f = 1;
}
else f = -1;
}
}
}
}
}
}
}
}
return f;
}
int cmp2(const void *a,const void *b)
{
struct Stu *aa=(Stu *)a;
struct Stu *bb=(Stu *)b;
int f = 0;
if(aa -> exam_number > bb -> exam_number) f = 1;
else f = -1;
return f;
}
int cmp3(const void *a,const void *b)
{
struct Stu *aa=(Stu *)a;
struct Stu *bb=(Stu *)b;
int f = 0;
if(aa -> date > bb ->date)
{
f = 1;
}
else
{
if(aa -> date < bb ->date)
{
f = -1;
}
else
{
if(aa -> exam_number > bb -> exam_number) f = 1;
else f = -1;
}
}
return f;
}
void case_1(char c,struct Stu student[4][10000],int n,FILE *q)
{
int i = 0;
int f = 1;
while(student[1][i].level != c && i < n)
{
i++;
}
while(student[1][i].level == c && i < n)
{
fprintf(q,"%c%03d%06ld%03d %d",student[1][i].level,student[1][i].exam_number,student[1][i].date,student[1][i].id_number,student[1][i].grade);
i++;
f = 0;
if(student[1][i].level == c && i < n) fprintf(q,"\n");
}
if (f) fprintf(q,"NA");
}
void case_2(struct Stu student[4][10000],int n,int exam,FILE *q)
{
int s = 0,i = 0;
int sum = 0;
while(student[2][i].exam_number != exam && i < n)
{
i++;
}
while(student[2][i].exam_number == exam && i < n)
{
s++;
sum += student[2][i].grade;
i++;
}
if(s != 0) fprintf(q,"%d %ld",s,sum);
else fprintf(q,"NA");
}
void case_3(struct Stu student[4][10000],int n,long date,FILE *q)
{
Room a[1000];
int i;
int f = 1;
for(i = 0;i < 1000;i++)
{
a[i].Room_no = i;
a[i].count = 0;
}
for(i = 0;i < n;i++)
{
if(student[3][i].date == date)
{
a[student[3][i].exam_number].count++;
}
}
qsort(a,1000,sizeof(Room),cmp4);
i = 0;
while(a[i].count != 0)
{
fprintf(q,"%d %d",a[i].Room_no,a[i].count);
i++;
if(a[i].count != 0)fprintf(q,"\n");
f = 0;
}
if (f) fprintf(q,"NA");
}
int cmp4(const void *a,const void *b)
{
struct Room *aa=(Room *)a;
struct Room *bb=(Room *)b;
int f = 0;
if(aa -> count < bb -> count)
{
f = 1;
}
else
{
if(aa -> count > bb -> count)
{
f = -1;
}
else
{
if(aa -> Room_no > bb -> Room_no) f = 1;
else f = -1;
}
}
return f;
}