今天帶三題題目,希望大家可以經過這三題的練習更加瞭解排序演算法與在競賽、解題中的使用
白話來說就是要求氣泡排序完數列最少需要交換幾次
由於題目的數列長度 最大只會是 ,因此直接做氣泡排序求出交換次數也可以過
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
while(cin >> n){
int arr[n + 10],ans = 0;
for(int i = 0;i < n;i++){
cin >> arr[i];
}
for(int i = 0;i < n - 1;i++){
for(int j = 0;j + 1 < n;j++){
if(arr[j] > arr[j + 1]){
swap(arr[j],arr[j + 1]);
ans++;
}
}
}
cout << "Minimum exchange operations : " << ans << "\n";
}
return 0;
}
基本上就是依照題目規則做排序,規則在以下做整理:
注意
負數的餘數計算和 C 語言裡的定義相同,即負數的餘數絕對不會大於零。例如 -100 MOD 3 = -1, -100 MOD 4 = 0 依此類推。
可以利用 C++ 內建的排序函式並搭配比較函式直接排序
#include <bits/stdc++.h>
using namespace std;
long long n,m;
bool cmp(long long a,long long b){
if(a % m != b % m){
return a % m < b % m;
}else{
if(abs(a) % 2 != abs(b) % 2){
return abs(a) % 2 > abs(b) % 2;
}else{
return abs(a) % 2 ? a > b : a < b;
}
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
while(cin >> n >> m && n && m){
cout << n << " " << m << "\n";
vector<long long> v(n);
for(auto &i : v){
cin >> i;
}
sort(v.begin(),v.end(),cmp);
for(auto &i : v){
cout << i << "\n";
}
}
cout << n << " " << m << "\n";
return 0;
}
本題是 2021 TOI 初選大家公認的簡單題,而這題剛好可以讓大家了解 sort 穩不穩定的區別,題目要讓大家將數列依照二進位中 的數量由小到大排序,而如果數量相同就依照輸入順序排序
可以發現它需要用到二進位中 的數量,所以在此題我使用 pair 來存數值和該數值的二進位中 的數量,而計算二進位中 的數量我使用 __builtin_popcount() 函式,可以直接取得數量,接下來在寫比較函式,並且因為他如果數量相同會需要依照輸入順序排序,因此須注意要使用 stable_sort()
#include <bits/stdc++.h>
using namespace std;
bool cmp(pair<long long,long long> a,pair<long long,long long> b){
return a.second < b.second;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
long long n;
cin >> n;
vector<pair<long long,long long>> v(n);
for(int i = 0;i < n;i++){
cin >> v[i].first;
v[i].second = __builtin_popcount(v[i].first);
}
stable_sort(v.begin(),v.end(),cmp);
for(auto &[i,j] : v){
cout << i << " ";
}
cout << "\n";
return 0;
}
可以看到有些的題目其實可以使用內建函式就好,不過還是得需要了解它的原理以及如何實作,並進而瞭解時間複雜度,才不會造成誤用或是錯估時間複雜度
明天還在思考要講貪心、二分搜還是簡單的 DFS、BFS,不過一樣會是分成講概念 + 帶幾題練習題,大家可以期待一下,或是敲碗要看什麼內容