zoukankan      html  css  js  c++  java
  • 蓝桥杯省赛备战笔记—— (四)使用sort排序——练习题

     例题:浮点数排序

     

     

    #include<stdio.h>
    #include<math.h>
    #include<iostream>
    #include<algorithm>
    #define EPSILON 1e-6
    using namespace std;
    double s[105];
    bool cmp(double a,double b){
        double aa = fabs(a - round(a));
        double bb = fabs(b - round(b));
        if(fabs(aa - bb) < EPSILON){
            return a < b;
        } //如果两个浮点数的与最近整数的差 相差小于指定的值,就认为两差数大小相等,当两差数大小相等时,就按原来的浮点数的值从小到大排序
        return aa < bb;    //否则,按照两差数 从小到大排序
    }
    int main(){int n;
        double x; 
        scanf("%d",&n);
        for(int i = 0;i < n;i++){
            scanf("%lf",&s[i]);
        }
        sort(s,s+n,cmp);
        for(int i  =0; i < n;i++){
            if(i == 0){
                printf("%.6f",s[i]);
            }else{
                printf(" %.6f",s[i]);
            }
        }
        
        return 0;
    }
    • fabs()   —— 对浮点数求绝对值
    • round() —— 四舍五入的整数,相当于是最近的整数

    例题:分数线

    某小学举办了一场校内的信息学竞赛选拔赛。现在
    同学们的成绩都出来了,负责信息学竞赛的老师需
    要确定最终选拔赛的获奖名单。
    为了鼓励大家,老师希望获奖人数不少于参赛总人
    数的一半。因此,老师需要确定一个获奖分数线,
    所有得分在分数线及以上的同学可以获奖。在满足
    .上面条件的情况下,老师希望获奖分数线越高越
    好。
    请同学们通过程序设计的方法来解决以上问题,确
    定获奖分数线和总获奖人数。

    输入格式:

     

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int s[10005];
    int main(){
        int n;
        scanf("%d",&n);
        for(int i= 0; i< n;i++){
            scanf("%d",&s[i]);    
        }
        sort(s,s+n,greater<int>());
        int x= s[(n-1)/2];
        printf("%d ",x);
        int sum = 0;
        for(int i = 0;i < n;i++){
            if(s[i] >= x)
                sum++;
            else
                break;
        }
        printf("%d",sum);
        return 0;
    }

    例题:交叉排序

    蒜头君很无聊,他想对数组中的某些元素进行排
    序。
    现在我们有N个数,他想先将数组中第l1到第r1
    的数字按从小到大的顺序排序。再将数组中第l2
    到第r2的数字按从大到小的顺序排序。
    我们帮他算一算数组排序后的结果吧~

     

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int a[10005];
    int main(){
        int n,l1,r1,l2,r2;
        scanf("%d%d%d%d%d",&n,&l1,&r1,&l2,&r2);
        for(int i = 0;i < n;i++){
            scanf("%d",&a[i]);
        }
        sort(a + l1 - 1,a + r1 );
        sort(a + l2- 1, a + r2,greater<int>());
        for(int i = 0;i < n;i++){
            if(i == 0)
                printf("%d",a[i]);
            else
                printf(" %d",a[i]);
        }
        return 0;
    }

    例题:红绿蓝

    蒜头君有一个罐子,里面装着红的、绿的、蓝的玻
    璃珠若干,分别用R、G、B表示。蒜头君希望
    把它们排成一行,并且按照字典序排列(即B ->
    G-> R的顺序)。然后以一红二绿三蓝为一-组串
    成一串幸运珠,多余的放回罐子里,那么他能串成
    多少串幸运珠呢?

    #include<stdio.h>
    #include<algorithm>
    #include<iostream>
    #include<string.h>
    #include<math.h>
    using namespace std;
    char s[10005];
    int main(){
        scanf("%s",s);
        int len = strlen(s);
        sort(s,s+len);
        printf("%s
    ",s);
        int r = 0;
        int g = 0;
        int b = 0;
        for(int i =0 ;i < len;i++){
            if(s[i] == 'R')
                r++;
            else if (s[i] == 'G')
                g++;
            else
                b++;
        }
        int mi = min(r,min(g/2,b/3));
        printf("%d",mi);
        return 0;
    }

     例题:整数排序进阶

    我们有N个正整数,均小于10000。现在需要将
    这些正整数按照该正整数每一位数字相加的和从小
    到大排序,即该正整数的每一位数字相加的和越小
    排位越靠前。如果各位相加和相等,则按照正整数
    的值从小到大排序。

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int s[105];
    bool cmp(int a,int b){
        int aa = a;
        int bb = b;
        int suma = 0;
        int sumb = 0;
        while(a != 0){
            suma += a % 10;
            a /= 10;
        }
        while(b != 0){
            sumb += b % 10;
            b /= 10;
        }
        if(suma == sumb)
            return aa < bb;
        return suma < sumb;
    }
    int main(){
        int n;
        scanf("%d",&n);
        for(int i = 0; i< n;i++){
            scanf("%d",&s[i]);
        }
        sort(s,s+n,cmp);
        for(int i =0 ;i < n;i++){
            if( i == 0)
                printf("%d",s[i]);
            else
                printf(" %d",s[i]);
        }    
        return 0;
    }

     例题:成绩排序

    蒜头君班上一共有n个同学,每个同学依次编号为
    1,2,...n,每个同学有一个分数。现在他请你帮
    忙做一份全班同学的成绩排名表。
    首先你需要按照分数从高到低将所有同学排序,再
    输出成绩单上每个同学的编号。
    保证任意两个同学的分数互不相同。

     

    #include<stdio.h>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    struct Stu{
        int score;
        int id;
    };
    bool cmp(Stu x,Stu y){
        return x.score > y.score;
    }
    Stu stu[105];
    int main(){
        int n;
        scanf("%d",&n);
        for(int i = 0;i < n;i++){
            int a;
            scanf("%d",&a);
            stu[i].score = a;
            stu[i].id = i+1;
        }
        sort(stu,stu+n,cmp);
        for(int i  =0; i < n;i++){
            if(i == 0)
                printf("%d",stu[i].id);
            else
                printf(" %d",stu[i].id);
        }
        return 0;
    }

    例题:成绩排序升级版

    小蒜所在的学校一开学就进行了一次摸底考试。摸
    底考试考了语文、数学、英语、科学共四门课程。
    小蒜的老师汇总成绩后列出了成绩单,其中包括每
    个同学的姓名和四科的成绩。现在老师希望表扬一
    每门课程考试得分前四名和总分前四名的同学,
    同分数的情况下,名字字典序更小的先表扬
    请你帮助老师写一个程序,快速完成这件事情吧。

    输入格式
    第一-行为学生人数N(4<= N ≤100)。
    之后N行依次为每个学生的姓名和语文、数学、
    英语、科学这四门课程的成绩,之间用一个空格隔
    开(成绩都大于等于0小于等于100)
    输出格式
    输出第一行为语文考试要表扬前四名的同学的姓
    名,之间用-一个空格隔开。

    输出第二行为数学考试要表扬前四名的同学的姓
    名,之间用一个空格隔开。
    输出第三行为英语考试要表扬前四名的同学的姓
    名,之间用一个空格隔开。
    输出第四行为科学考试要表扬前四名的同学的姓
    名,之间用一个空格隔开。
    输出第五行为总分要表扬前四名的同学的姓名,之
    间用一个空格隔开。

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    struct Stu{
        char name[10];
        int score[4];
    };
    Stu stu[105];
    void print(int n){
        n = n - 1;
        for(int i = 0; i < n;i++){
            if(i == 0)
                printf("%s",stu[i].name);
            else
                printf(" %s",stu[i].name);
        }
        printf("
    ");
    }
    bool cmp1(Stu a,Stu b){
        if(a.score[0] != b.score[0])
            return a.score[0] > b.score[0];
        return strcmp(a.name, b.name) < 0;  //strcmp(x,y). 如果字符串x 按字典序小于y,则返回小于0的值
        //如果为真,则 a 排在 b 前面  
    }
    bool cmp2(Stu a,Stu b){
        if(a.score[1] != b.score[1])
            return a.score[1] > b.score[1];
        return strcmp(a.name, b.name) < 0; 
    }
    bool cmp3(Stu a,Stu b){
        if(a.score[2] != b.score[2])
            return a.score[2] > b.score[2];
        return strcmp(a.name, b.name) < 0;  //strcmp(x,y). 如果字符串x 按字典序小于y,则返回小于0的值
        //如果为真,则 a 排在 b 前面  
    }
    bool cmp4(Stu a,Stu b){
        if(a.score[3] != b.score[3])
            return a.score[3] > b.score[3];
        return strcmp(a.name, b.name) < 0;  //strcmp(x,y). 如果字符串x 按字典序小于y,则返回小于0的值
        //如果为真,则 a 排在 b 前面  
    }
    bool cmp_all(Stu a,Stu b){
        int sum_a = 0;
        int sum_b = 0;
        for(int i = 0 ;i < 4;i++){
            sum_a += a.score[i];
            sum_b += b.score[i];
        }
        if(sum_a != sum_b)
            return sum_a > sum_b;
        return strcmp(a.name, b.name) < 0;  //strcmp(x,y). 如果字符串x 按字典序小于y,则返回小于0的值
        //如果为真,则 a 排在 b 前面  
    }
    int main(){
        int N;    
        scanf("%d",&N);
        for(int i =  0;i < N;i++){
            scanf("%s",stu[i].name);
            for(int j = 0;j < 4;j++){
                scanf("%d",&stu[i].score[j]);
            }
        }
        sort(stu,stu+N,cmp1);
        print(N);
        sort(stu,stu+N,cmp2);
        print(N);
        sort(stu,stu+N,cmp3);
        print(N);
        sort(stu,stu+N,cmp4);
        print(N);
        sort(stu,stu+N,cmp_all);
        print(N);
        return 0;
    }

    例题:抢气球

    教室的墙上挂满了气球,五颜六色,小朋友们非常
    喜欢。
    刚一下课,小朋友们就打算去抢这些气球。每个气.
    球在墙上都有一定的高度,只有当小朋友跳起来
    时,手能够到的高度大于等于气球的高度,小朋友
    才能摘到这个气球。为了公平起见,老师让跳的低
    的小朋友先摘,跳的高的小朋友后摘。小朋友都很
    贪心,每个小朋友在摘气球的时候都会把自己能摘
    的气球都摘掉。
    很巧的是,小朋友们跳起来手能够着的高度都不一
    样,这样就不会有跳起来后高度相同的小朋友之间
    发生争执了。

     样例2:

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    struct Child{
        int id;
        int h;
    };
    Child ch[1005];
    int flag[1005];
    int child_get[1005];
    int ball_h[1005]; 
    
    bool cmp(Child x,Child y){
        return x.h < y.h;
    }
    int main(){
        int n,m;
        scanf("%d %d",&n,&m);
        for(int i = 0 ;i < n;i++){
            scanf("%d",&ch[i].h);
            ch[i].id = i;
        }
        for(int i = 0;i < m;i++){
            scanf("%d",&ball_h[i]);
        }
        sort(ch,ch+n,cmp);
        for(int i = 0; i < n;i++){
            for(int j = 0;j < m;j++){
                if(ball_h[j] <= ch[i].h && flag[j] == 0){//如果气球高度可以摘到,同时没有被摘下来
                    flag[j] = 1;
                    child_get[ch[i].id]++; //排序前的顺序
                }
            }
        }
        for(int i = 0 ;i < n;i++){
            printf("%d
    ",child_get[i]);
        }
        return 0;
    }

     例题:抢气球升级版

     只有n m 的规模发生了变化,增大到 10^ 5 级,时间限制1s ,显然,上方的做法会超时

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    struct Child{
        int id;
        int h;
    };
    Child ch[1005];
    int child_get[1005];
    int ball_h[1005]; 
    
    bool cmp(Child x,Child y){
        return x.h < y.h;
    }
    int main(){
        int n,m;
        scanf("%d %d",&n,&m);
        for(int i = 0 ;i < n;i++){
            scanf("%d",&ch[i].h);
            ch[i].id = i;
        }
        for(int i = 0;i < m;i++){
            scanf("%d",&ball_h[i]);
        }
        sort(ch,ch+n,cmp);
        
        //只需要将气球也按高度排序即可,优化内部for循环,省去扫描已经被摘走的气球
        sort(ball_h,ball_h + m);
        int p = 0; 
        for(int i = 0; i < n;i++){
             while(p < m && ball_h[p] <= ch[i].h ){
                 child_get[ch[i].id]++;
                p++;
             }
        }
        //时间复杂度 由O(n*m)--> O(n+m) 
        for(int i = 0 ;i < n;i++){
            printf("%d
    ",child_get[i]);
        }
        return 0;
    }
  • 相关阅读:
    BZOJ 2034 【2009国家集训队】 最大收益
    vijos P1780 【NOIP2012】 开车旅行
    BZOJ 2115 【WC2011】 Xor
    BZOJ 3631 【JLOI2014】 松鼠的新家
    BZOJ 4717 改装
    BZOJ 2957 楼房重建
    BZOJ 4034 【HAOI2015】 T2
    BZOJ 1834 【ZJOI2010】 network 网络扩容
    BZOJ 2440 【中山市选2011】 完全平方数
    BZOJ 2733 【HNOI2012】 永无乡
  • 原文地址:https://www.cnblogs.com/expedition/p/12315215.html
Copyright © 2011-2022 走看看