首先说一下最后一个测试点的问题,要注意最终成绩就是四舍五入过的整数,也就是说98.6和98.7成绩是一样的,着实被恶心到了,害我搞了半天。
题目
对于在中国大学MOOC(http://www.icourse163.org/ )学习“数据结构”课程的学生,想要获得一张合格证书,必须首先获得不少于200分的在线编程作业分,然后总评获得不少于60分(满分100)。总评成绩的计算公式为 G=(Gmid−term×40%+Gfinal×60%),如果 Gmid−term>Gfinal;否则总评 G 就是 Gfinal。这里 Gmid−term 和 Gfinal 分别为学生的期中和期末成绩。
现在的问题是,每次考试都产生一张独立的成绩单。本题就请你编写程序,把不同的成绩单合为一张。
输入格式:
输入在第一行给出3个整数,分别是 P(做了在线编程作业的学生数)、M(参加了期中考试的学生数)、N(参加了期末考试的学生数)。每个数都不超过10000。
接下来有三块输入。第一块包含 P 个在线编程成绩 Gp;第二块包含 M 个期中考试成绩 Gmid−term;第三块包含 N 个期末考试成绩 Gfinal。每个成绩占一行,格式为:学生学号 分数
。其中学生学号
为不超过20个字符的英文字母和数字;分数
是非负整数(编程总分最高为900分,期中和期末的最高分为100分)。
输出格式:
打印出获得合格证书的学生名单。每个学生占一行,格式为:
学生学号
Gp Gmid−term Gfinal G
如果有的成绩不存在(例如某人没参加期中考试),则在相应的位置输出“−1”。输出顺序为按照总评分数(四舍五入精确到整数)递减。若有并列,则按学号递增。题目保证学号没有重复,且至少存在1个合格的学生。
输出样例:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct student{
char name[25]; /*储存学号*/
int p; /*储存在线编程成绩*/
int m; /*储存期中考试成绩*/
int n; /*储存期末成绩*/
int zong; /*储存期终成绩*/
int check; /*是否合格*/
}stu;
int comp1(const void* a,const void* b); /*按照学号升序排列*/
int comp2(const void* a,const void* b); /*排序总函数*/
int comp3(const void* a,const void* b); /*按学号查找函数*/
int main(){
int p,m,n,i=0,x=0; /*储存各类考试成绩*/
int mp,mm,mn;
char name[25];
stu a[100000]; /*这里是100000个学生*/
stu *dent;
scanf("%d %d %d",&p,&m,&n);
while(p--)
{scanf("%s %d",name,&mp);
getchar();
strcpy(a[i].name,name);
a[i].p=mp;
a[i].m=-1; /*其他两项成绩初始化,默认没有*/
a[i].n=-1;
i++;
}
qsort(a,i,sizeof(stu),comp1);
while(m--)
{scanf("%s %d",name,&mm);
getchar();
dent=(stu*)bsearch(name,a,i,sizeof(stu),comp3);
if(dent!=0) /*若在线编程没有成绩,则一定不合格,不考虑*/
dent->m=mm;
}
while(n--)
{scanf("%s %d",name,&mn);
getchar();
dent=(stu*)bsearch(name,a,i,sizeof(stu),comp1);
if(dent!=0)
dent->n=mn;
}
for(x=0;x<i;x++) /*这个循环计算最终成绩,并判定是否合格*/
{if(a[x].m<a[x].n)
{a[x].zong=a[x].n;
if(a[x].zong>=60&&a[x].p>=200)
{a[x].check=1;
}
else
a[x].check=0;
continue;
}
a[x].zong=(int)(a[x].m*0.4+a[x].n*0.6+0.5); /*四舍五入后储存*/
if(a[x].zong+0.5>=60&&a[x].p>=200)
{a[x].check=1;
}
else
a[x].check=0;
}
qsort(a,i,sizeof(stu),comp2); /*排序*/
for(x=0;x<i&&a[x].check==1;x++) /*输出*/
printf("%s %d %d %d %d\n",a[x].name,a[x].p,a[x].m,a[x].n,a[x].zong);
}
int comp1(const void* a,const void* b)
{stu* x=(stu*)a;
stu* y=(stu*)b;
return strcmp(x->name,y->name); /*按名字升序*/
}
int comp2(const void* a,const void* b)
{stu* x=(stu*)a;
stu* y=(stu*)b;
if(x->check != y->check) /*合格在前*/
return y->check - x->check;
else if(x->zong != y->zong) /*最终成绩高的在前*/
return y->zong - x->zong;
else /*按名字升序*/
return strcmp(x->name,y->name);
}
int comp3(const void* a,const void* b)
{char *x=(char*)a;
stu *y=(stu*)b;
return strcmp(x,y->name); /*查找*/
}
需要注意的地方写在开头和注释里了,之前换过一种方法,但运行时间半斤八两,这个代码相对简洁。