# 0-11 struct、0-12 變數的作用範圍及0-13 排序 講義不是我寫的,網址在此 https://emanlaicepsa.github.io/2020/10/21/0-index/ 我只是將自己寫的練習題程式碼記錄下來。 最後更新日期:2024年10月6日 ## [ZeroJudge: a104. 排序](https://zerojudge.tw/ShowProblem?problemid=a104) ### Python 程式碼 執行時間最久約為 23 ms,使用記憶體最多約為 3.6 MB,通過測試。 ```python= import sys for line in sys.stdin: n = int(line) data = list(map(int, sys.stdin.readline().split())) data.sort() print(*data) ``` ### C++ 程式碼 執行時間最久約為 9 ms,使用記憶體最多約為 276 kB,通過測試。 ```cpp= #include <iostream> #include <algorithm> using namespace std; int main() { int n; while(cin >> n) { int data[n]; for(int i=0; i<n; i++) cin >> data[i]; sort(data, data+n); for(int i=0; i<n; i++) cout << data[i] << " \n"[i == n-1]; } } ``` ## [ZeroJudeg: a233. 排序法~~~ 挑戰極限](https://zerojudge.tw/ShowProblem?problemid=a233) ### Python 程式碼 執行時間最久約為 0.9 s,使用記憶體最多約為 64.6 MB,通過測試。 ```python= n = int(input()) data = list(map(int, input().split())) data.sort() print(*data) ``` ### C++ 程式碼 執行時間最久約為 0.5 s,使用記憶體最多約為 2.2 MB,通過測試。 ```cpp= #include <iostream> #include <algorithm> using namespace std; int main() { int n; cin >> n; int data[n]; for(int i=0; i<n; i++) cin >> data[i]; sort(data, data+n); for(int i=0; i<n; i++) cout << data[i] << " \n"[i == n-1]; return 0; } ``` ## [ZeroJudge: a915. 二維點排序](https://zerojudge.tw/ShowProblem?problemid=a915) ### Python 程式碼 寫法1,用 functools 函式庫的 cmp_to_key 自訂比較式。執行時間最久約為 33 ms,使用記憶體最多約為 4.2 MB,通過測試。 ```python= import functools class Point: def __init__(self, x, y): self.x = x self.y = y def mycmp(p1, p2): if p1.x > p2.x: return 1 elif p1.x == p2.x: if p1.y > p2.y: return 1 else: return -1 else: return -1 n = int(input()) points = [] for _ in range(n): x, y = map(int, input().split()) points.append(Point(x, y)) points.sort(key=functools.cmp_to_key(mycmp)) for point in points: print("{:d} {:d}".format(point.x, point.y)) ``` 寫法2,用二維串列儲存資料再排序。執行時間最久約為 24 ms,使用記憶體最多約為 3.8 MB,通過測試。 ```python= n = int(input()) points = [] for _ in range(n): points.append(list(map(int, input().split()))) points.sort() for point in points: print(*point) ``` ### C++ 程式碼 執行時間最久約為 3 ms,使用記憶體最多約為 348 kB,通過測試。 ```cpp= #include <iostream> #include <algorithm> using namespace std; struct Point { int x, y; }; bool mycmp(Point p1, Point p2) { if (p1.x != p2.x) return p1.x < p2.x; else return p1.y < p2.y; } int main() { ios::sync_with_stdio(0),cin.tie(0); int n; cin >> n; Point points[n]; for(int i=0; i<n; i++) cin >> points[i].x >> points[i].y; sort(points, points+n, mycmp); for(int i=0; i<n; i++) cout << points[i].x << " " << points[i].y << "\n"; return 0; } ``` 執行時間最久約為 3 ms,使用記憶體最多約為 344 kB,通過測試。 ```cpp= #include <iostream> #include <algorithm> #include <utility> using namespace std; int main() { ios::sync_with_stdio(0),cin.tie(0); int n; cin >> n; pair<int, int> points[n]; for(int i=0; i<n; i++) cin >> points[i].first >> points[i].second; sort(points, points+n); for(int i=0; i<n; i++) cout << points[i].first << " " << points[i].second << "\n"; return 0; } ``` ## [TOJ: 15 / 打獵分配問題](https://toj.tfcis.org/oj/pro/15/) ### Python 程式碼 第3筆測資超時。 ```python= from functools import cmp_to_key import sys def mycmp(a, b): # 資料依序為身份、年齡、名字 if a[0] > b[0]: return 1 # 身份編號大的放後面 elif a[0] < b[0]: return -1 # 身份編號小的放前面 elif a[1] != b[1]: # 身份編號相同,而且年齡不同 if a[0] == 5 and b[0] == 5: # 身份編號都是 5 if a[1] > b[1]: return 1 # 年齡大的放後面 elif a[1] < b[1]: return -1 # 年齡小的放前面 else: # 年齡相同 if a[2] > b[2]: return 1 # 名字字典順序大的放後面 else: return -1 # 名字字典順序小的放前面 else: # 身份編號相同而且都不是5號 if a[1] < b[1]: return 1 # 年齡小的放後面 elif a[1] > b[1]: return -1 # 年齡大的放前面 else: # 年齡相同 if a[2] > b[2]: return 1 # 名字字典順序大的放後面 else: return -1 # 名字字典順序小的放前面 else: # 身份編號相同、年齡相同 if a[2] > b[2]: return 1 # 名字字典順序大的放後面 else: return -1 # 名字字典順序小的放前面 role = {"elder": 1, "nursy": 2, "kit": 3, "warrior": 4, "appentice": 5, "medicent": 6, "deputy": 7, "leader": 8} for line in sys.stdin: n, m = map(int, line.split()) cats = [] for _ in range(n): na, ro, yr = input().split() cats.append([role[ro], int(yr), na]) cats.sort(key = cmp_to_key(mycmp)) if n < m: m = n for i in range(m): print(cats[i][2]) ``` ### C++ 程式碼 執行時間最久約為 763 ms,使用記憶體最多約為 10612 kB,通過測試。 ```cpp= #include <iostream> #include <string> #include <algorithm> #include <map> using namespace std; struct Cat { // 自訂類別 string name; // 名字 int role, year; // 身份、年齡 }; bool mycmp(Cat a, Cat b) { // 自訂比較式 if (a.role != b.role) { // 如果身份不同 return a.role < b.role; // 依照身份編號由小到大排序 } else if (a.year != b.year) { // 如果身份相同而且年齡不同 if (a.role == 5 && b.role == 5) return a.year < b.year; // 如果身份都是 appentice,依照年齡由小到大排序 else return a.year > b.year; // 其它身份,依照年齡由大到小排序 } else return a.name < b.name; // 如果身份、年齡都相同,依照名字字典順序排序 } int main() { ios::sync_with_stdio(0); cin.tie(0); map<string, int> roles = {{"elder", 1}, {"nursy", 2}, {"kit", 3}, {"warrior", 4}, // 身份對應的編號 {"appentice", 5}, {"medicent", 6}, {"deputy", 7}, {"leader", 8}}; int n, m; // 貓的數量 n,食物數量 m while(cin >> n >> m) { // 多筆測資 Cat cats[n]; // 儲存 n 隻貓資料的陣列 for(int i=0; i<n; i++) { // 讀取 n 隻貓的資料 string na, ro; int yr; cin >> na >> ro >> yr; cats[i].name = na; cats[i].role = roles[ro]; cats[i].year = yr; } sort(cats, cats+n, mycmp); // 依照 mycmp 排序 if (n < m) m = n; // 如果 n 小於 m,重設 m 為 n for(int i=0; i<m; i++) cout << cats[i].name << "\n"; // 輸出前 m 隻貓的名字 } return 0; } ``` ## [TOJ: 539 / B. 國手](https://toj.tfcis.org/oj/pro/539/) ### Python 程式碼 執行時間最久約為 644 ms,使用記憶體最多約為 36900 kB,通過測試。 ```python= n, k = map(int, input().split()) # 天數 n,標準 k a = list(map(int, input().split())) # 裝弱的分數 b = list(map(int, input().split())) # 正常發揮的分數 d = [0]*n # 正常發揮的分數 - 裝弱的分數 tot = 0 # 裝弱的分數總和 for i in range(n): # 依序讀取每天的分數 d[i] = b[i] - a[i] # 更新第 i 天的分差 tot += b[i] # 更新 tot # end of for loop d.sort() # 分差由小到大排序 flag = True # 是否及格 for i in range(n): # 依序檢查 n 項 if tot - d[i] < k: # 如果 tot 減去當天裝弱的分差小於 k print(i) # 印出 i,即為可以裝弱的天數 flag = False # 已經不及格 break # 中止迴圈 tot -= d[i] # 更新總分,扣掉分差 # end of for loop if flag: print(n) # 如果 n 天都裝弱仍然及格,印出 n ``` ### C++ 程式碼 這題要用 long long,用 int 會溢位。執行時間最久約為 52 ms,使用記憶體最多約為 5080 kB,通過測試。 ```cpp= #include <iostream> #include <algorithm> typedef long long LL; using namespace std; int main() { ios::sync_with_stdio(0); cin.tie(0); LL n, k; cin >> n >> k; // 天數 n,標準 k LL a[n], b[n], d[n], tot = 0; // 裝弱的分數a,正常發揮的分數b,b-a,b的總和 for(LL i=0; i<n; i++) cin >> a[i]; // 依序讀取a for(LL i=0; i<n; i++) { cin >> b[i]; // 依序讀取b d[i] = b[i] - a[i]; // 更新第 i 天的分差 tot += b[i]; // 更新 tot } sort(d, d+n); // 分差由小到大排序 bool flag = true; // 是否及格 for(LL i=0; i<n; i++) { // 依序檢查 n 項 if (tot - d[i] < k) { // 如果 tot 減去當天裝弱的分差小於 k cout << i << "\n"; // 印出 i,即為可以裝弱的天數 flag = false; // 已經不及格 break; // 中止迴圈 } tot -= d[i]; // 更新總分,扣掉分差 } if (flag) cout << n << "\n"; // 如果 n 天都裝弱仍然及格,印出 n return 0; } ``` ## [ZeroJudge: c471. 物品堆疊](https://zerojudge.tw/ShowProblem?problemid=c471) 以下內容引用自另一篇文章〈[APCS實作題2017年10月第4題:物品堆疊 (Stacking)](https://hackmd.io/@yizhewang/r1LDMAH0s)〉 {%hackmd @yizhewang/r1LDMAH0s %} ## [TOJ: 11 / bubble](https://toj.tfcis.org/oj/pro/11/) 這題不能真的跑氣泡排序,一定會超時。改用 C++ 及合併排序計算次數還是超時。 ### Python 程式碼 ```python= ``` ### C++ 程式碼 ```cpp= ``` ------ ###### tags:`演算法`、`APCS`、`Python`、`C++`