藍橋杯省賽備戰筆記—— (四)使用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\n",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("\n");
}
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\n",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\n",child_get[i]);
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM