与班尼特·胡迪一起拿奖学金 AC

Time Limit:   2 s      Memory Limit:   256 MB

Description

班尼特·胡迪这学期的体测终于上80分了,当期末考试的成绩单和综测表出来之后他想要计算自己究竟能不能拿到奖学金。班尼特·胡迪所在的计算机学院的奖学金评选方法为基本素质优秀,发展素质良好或优秀,体测成绩达到80分及以上,每班只有绩点前25%(向上取整)且符合以上条件的学生才有资格评选奖学金。

班尼特·胡迪由于沉浸在体测上80分的喜悦中无法自拔,他决定请你帮他写一个程序,根据所给班级的成绩单和综测表,综合计算出班尼特·胡迪所在班级哪些人有资格获得奖学金。

Input

输入在第一行给出1个整数N,表示班尼特·胡迪所在班级的人数(1<=N<=105)

接下来有两块输入。第一块包括了N个学生的成绩单,每个成绩占一行,格式为:姓名 体测成绩S体测 平均绩点SGPA。其中姓名为不超过20个可见字符的字符串;0<=S体测<=100 (整数)0.0<=SGPA<=5.0 。第二块包括了N个学生的综测表,每人的综测评价占一行,格式为:姓名 基本素质 发展素质。其中姓名为不超过20个可见字符的字符串,基本素质与发展素质都分为四个等级,如果是优秀则为2,良好则为1,及格为0,不及格为-1

Output

打印输出有资格获得奖学金的学生名单,每个学生占一行,格式为

姓名 基本素质 发展素质 S体测 SGPA

平均绩点 SGPA 保留小数点后两位,输出顺序为按照 SGPA 递减。若有并列,则按姓名字典序排序。题目保证姓名没有重复,且至少存在1个能够获得奖学金的学生。 

 

Samples

input:
5
John 80 3.82
Caesar 79 3.21
Bennett 81 3.77
Alice 66 2.4
Russell 90 2.73
Alice 1 -1
Russell 2 2
Bennett 2 1
Caesar 2 0
John 2 2
output:
John 2 2 80 3.82
Bennett 2 1 81 3.77

Author

Source

杭州师范大学第十一届程序设计竞赛

题解:题目不难,就按要求所说,找到gpa排名前25%的(向上取整),同时体育成绩、基本素质和优秀素质要达标的人。

思路:这道题难点在于可能会超时。数据扫两个n进来,要把前面一段与后面一段对应,需要用二分法查找。我用了两遍sort,第一次是为了对应名字方便,第二次是按gpa和姓名字典序排序。题目要求是2s,最后我代码勉强349ms。。比较菜的代码。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<algorithm>
 7 using namespace std;
 8 struct student               //建立结构体把信息存入
 9 {
10     char name[50];
11     int jb;
12     int fz;
13     int sport;
14     double gpa;
15 }student1[100005],student2[100005];
16 bool compare1(const student a,const student b)     //字典序排序
17 {
18     return strcmp(a.name,b.name)<0;
19 }
20 
21 bool compare2(const student a,const student b)     //gpa加字典序排序
22 {
23     if(a.gpa!=b.gpa) return a.gpa>b.gpa;
24     else return strcmp(a.name,b.name)<0;
25 }
26 int main()
27 {
28     int n,i,m,l,r;
29     scanf("%d",&n);
30     for(int i=0;i<n;i++)
31     {
32         scanf("%s %d %lf",student1[i].name,&student1[i].sport,&student1[i].gpa);
33     }
34     for(int i=0;i<n;i++)
35     {
36         scanf("%s %d %d",student2[i].name,&student2[i].jb,&student2[i].fz);
37     }
38     sort(student2,student2+n,compare1);        //将后面一段按字典序排序
39     /*for(int i=0;i<n;i++)
40     {
41         printf("%s %d %d\n",student2[i].name,student2[i].jb,student2[i].fz);     //看一下排序结果
42     }
43     */
44     
45     for(i=0;i<n;i++)          //二分法查找两段相同的姓名,把第二段信息基本素质和优秀素质录入第一段
46     {
47         l=0;
48         r=n-1;
49         while(l<=r)
50         {
51             m=(l+r)/2;
52             if(strcmp(student1[i].name,student2[m].name)==0)
53             {
54                 student1[i].jb=student2[m].jb;
55                 student1[i].fz=student2[m].fz;
56                 break;
57             }
58             else if(strcmp(student1[i].name,student2[m].name)>0)
59             {
60                 l=m+1;
61             }
62             else
63                 r=m-1;
64         }
65     }
66     sort(student1,student1+n,compare2);         //第一段数据排序
67     /*for(int i=0;i<n;i++)         //检验排序结果
68     {
69         printf("%s %d %d %d %.2lf\n",student1[i].name,student1[i].jb,student1[i].fz,student1[i].sport,student1[i].gpa);
70     }
71     */
72     for(i=0;i<=(n*0.25+0.5);i++)           //找到gpa前25%人并符合其它要求的人,题目要求向上取整
73     {
74         if(student1[i].sport>=80&&student1[i].jb>=2&&student1[i].fz>=1)
75             printf("%s %d %d %d %.2lf\n",student1[i].name,student1[i].jb,student1[i].fz,student1[i].sport,student1[i].gpa);
76     }
77     return 0;
78 }