例題:浮點數排序
#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; }