1482. 奖学金(关于结构体与qsort的思考)

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金。期末,每个学生都有3门课的成绩:语文、数学、英语。先按总分从高到低排序,如果两个同学总分相同,再按语文成绩从高到低排序,如果两个同学总分和语文成绩都相同,那么规定学号小的同学排在前面,这样,每个学生的排序是唯一确定的。
任务:先根据输入的3门课的成绩计算总分,然后按上述规则排序,最后按排名顺序输出前5名学生的学号和总分。注意,在前5名同学中,每个人的奖学金都不相同,因此,你必须严格按上述规则排序。例如,在某个正确答案中,如果前两行的输出数据(每行输出两个数:学号、总分)是:
7 279
5 279
这两行数据的含义是:总分最高的两个同学的学号依次是7号、5号。这两名同学的总分都是279(总分等于输入的语文、数学、英语三科成绩之和),但学号为7的学生语文成绩更高一些。如果你的前两名的输出数据是:
5 279
7 279
则按输出错误处理,不能得分。

Input

输入包含多组测试数据,每个测试数据有n+1行。
第1行为一个正整数n,表示该校参加评选的学生人数。
第2到n+1行,每行有3个用空格隔开的数字,每个数字都在0到100之间。第j行的3个数字依次表示学号为j-1的学生的语文、数学、英语的成绩。每个学生的学号按照输入顺序编号为1~n(恰好是输入数据的行号减1)。
所给的数据都是正确的,不必检验。

Output

对于每个测试数据输出5行,每行是两个用空格隔开的正整数, 依次表示前5名学生的学号和总分。两个相邻测试数据间用一个空行隔开。

Sample Input

6
90 67 80
87 66 91
78 89 91
88 99 77
67 89 64
78 89 98
8
80 89 89
88 98 78
90 67 80
87 66 91
78 89 91
88 99 77
67 89 64
78 89 98
Sample Output

6 265
4 264
3 258
2 244
1 237

8 265
2 264
6 264
1 258
5 258
Problem Source

NOIP 2007

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct edg{
    int num;
    int chi;
    int math;
    int eng;
    int total;
}stu[100];
int Comp(const void*p1,const void*p2)
{
    struct edg*c=(struct edg*)p1;
    struct edg*d=(struct edg*)p2;
    if(c->total != d->total)
        return c->total < d->total?1:-1;
    else if (c->chi != d->chi) {
        return c->chi < d->chi?1:-1;
    }
    return c->num > d->num?1:-1;
}
//qsort比较函数

int main() {
    int n;
    scanf("%d", &n);
    while (n) {
        for (int i = 0; i < n; i++) {
        stu[i].num = i + 1;
        scanf("%d%d%d", &stu[i].chi, &stu[i].math, &stu[i].eng);
        stu[i].total = stu[i].chi + stu[i].math + stu[i].eng;
    }
    qsort(stu, n, sizeof(stu[0]), Comp);
    for (int i = 0; i < 5; i++) {
        printf("%d %d\n", stu[i].num, stu[i].total);
    }
        scanf("%d", &n);
    }
    return 0;
}

cpp答案!

#include<iostream>  
#include<queue>  
using namespace std;  

struct Node  
{  
    int snum;//学号  
    int chinese;  
    int math;  
    int english;  
    int sum;//总分  
};  

struct cmp  
{  
    bool operator()(Node n1, Node n2)  
    {  
        if(n1.sum != n2.sum)  
        {  
            return n1.sum < n2.sum;  
        }  
        else  
        {  
            if(n1.chinese != n2.chinese)//总分相同,比较语文成绩  
            {  
                return n1.chinese < n2.chinese;  
            }  
            else  
            {  
                return n1.snum > n2.snum;//小学号的优先  
            }  
        }  
    }  
};  

int main()  
{  
    int num;  
    bool flag = false;  
    while(cin >> num)  
    {  
        if(flag)  
            cout << endl;  
        flag = true;  
        priority_queue<Node, vector<Node>, cmp> Q;  
        for(int i = 1; i <= num; i++)  
        {  
            Node n;  
            cin >> n.chinese;  
            cin >> n.math;  
            cin >> n.english;  
            n.snum = i;//学号  
            n.sum = n.chinese + n.math + n.english;  
            Q.push(n);  
        }  

        for(int i = 1; i <= 5; i++)  
        {  
            cout << Q.top().snum << " " << Q.top().sum << endl;  
            Q.pop();  
        }  
    }  
    return 0;  
}  

补充:

结构体替换的函数

void swap(struct edg *a,struct edg *b)
{
    struct edg temp;
    temp=*a;
    *a=*b;
    *b=temp;
}

关于qsort的五种种用法

compare( (void ) & elem1, (void ) & elem2 );
Compare 函数的返回值 描述
< 0 elem1将被排在elem2前面
0 elem1 等于 elem2
.>0 elem1 将被排在elem2后

void QuickSort(int h,int t)//快排的实现!
{
     if(h>=t)
         return;
     int mid=(h+t)/2,i=h,j=t,x;
     x=a[mid];
     while(1)
     {
         while(a[i]<x) i++;
         while(a[j]>x) j--;
         if(i>=j) break;
         temp=a[i];
         a[i]=a[j];
         a[j]=temp;
     }
     a[mid]=a[j];
     a[j]=x;
     QuickSort(h,j-1);
     QuickSort(j+1,t);
     return;
}

1 数字的排序

int comp(const void *a, const void *b) {
    return *(int*)*a - *(int*)b;

从小到大!

2 对char类型的排序(按字典序)

int cmp( const void *a , const void *b ) 
{ 
return *(char *)a - *(char *)b; 
} 
qsort(word,100,sizeof(word[0]),cmp); 

3 对double类型的排序
这里做个注释,本来是因为要判断如果a==b返回0的,但是严格来说,两个double数是不可能相等的,只能说fabs(a-b)<1e-20之类的这样来判断,所以这里只返回了1和-1

#include <stdio.h>
#include <stdlib.h>
double s[1000];
int i,n;
int cmp(const void * a, const void * b)
{
     return((*(double*)a-*(double*)b>0)?1:-1);
}
int main()
{
     scanf("%d",&n);
     for(i=0;i<n;i++) scanf("%lf",&s[i]);

     qsort(s,n,sizeof(s[0]),cmp);

     for(i=0;i<n;i++) printf("%lf ",s[i]);

     return(0);
}

4 对结构体的排序
包括一级,二级……实际上都是相同的,只是在cmp函数中有所不同。

struct In 
{ 
double data; 
int other; 
}s[100] 

int cmp( const void *a ,const void *b) 
{ 
return (*(struct In *)a).data > (*(struct In *)b).data ? 1 : -1; //一定是1和-1!!
} 

5 按字符串的字典序

struct In 
{ 
int data; 
char str[100]; 
}s[100]; 

//按照结构体中字符串str的字典顺序排序 

int cmp ( const void *a , const void *b ) 
{ 
return strcmp( (*(struct In *)a)->str , (*(struct In *)b)->str ); 
} 
qsort(s,100,sizeof(s[0]),cmp); 

补充:
struct 和 typedef struct的区别:
http://www.cnblogs.com/qyaizs/articles/2039101.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
谁拿了最多奖学金 • 某校的惯例是在每学期的期末考试之后发放奖学金。发放的奖学金共有五种,获取的条件各自不同: • 1) 院士奖学金,每人8000元,期末平均成绩高于80分( >80),并且在本学期内发表1篇或1篇以上论文的学生均可获得; • 2) 五四奖学金,每人4000元,期末平均成绩高于85分( >85),并且班级评议成绩高于80分(>80)的学生均可获得; • 3) 成绩优秀奖,每人2000元,期末平均成绩高于90分( >90)的学生均可获得; 4) 西部奖学金,每人1000元,期末平均成绩高于85分( >85)的西部省份学生均可获得;5) 班级贡献奖,每人850元,班级评议成绩高于80分(>80)的学生干部均可获得; • 只要符合条件就可以得奖,每项奖学金的获奖人数没有限制,每名学生也可以同时获得多项奖学金。 • 例如姚林的期末平均成绩是87分,班级评议成绩82分,同时他还是一位学生干部,那么他可以同时获得五四奖学金 和班级贡献奖,奖金总数是4850元。现在给出若干学生的相关数据,请计算哪些同学获得的奖金总数最高(假设总 有同学能满足获得奖学金的条件)。 Input 输入的第一行是一个整数N(1 <= N <= 100),表示学生的总数。 • 接下来的N行每行是一位学生的数据,从左向右依次是姓名,期末平均成绩,班级评议成绩,是否是学生干部,是 否是西部省份学生,以及发表的论文数。姓名是由大小写 英文字母组成的长度不超过20的字符串(不含空格);期末平均成绩和班级评议成绩都是0到100之间的整数(包括0和100);是否是学生干部和是否是西部省份学生分别用一个字符表示,Y表示是,N表示不是;发表的论文数是0 到10的整数(包括0和10)。每两个相邻数据项之间用一个空格分隔。 Output 输出包括三行,第一行是获得最多奖金的学生的姓名,第二行是这名学生获得的奖金总数。如果有两位或两位以上 的学生获得的奖金最多,输出他们之中在输入文件中出现 最早的学生的姓名。第三行是这N个学生获得的奖学金的总数。 • • Sample Input Sample Output 4 YaoLin 87 82 Y N 0 ChenRuiyi ChenRuiyi 88 78 N Y 1 9000 LiXin 92 88 N N 0 28700 ZhangQin 83 87 Y N 1

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值