【個人筆記】C++ ZeroJudge 基礎題庫解題(純練習) - part 3
a020:https://zerojudge.tw/ShowProblem?problemid=a020
難度:★☆☆☆☆
流程控制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| #include <iostream> #include <string>
using namespace std;
int main() { int mapping[26] = { 10, 11, 12, 13, 14, 15, 16, 17, 34, 18, 19, 20, 21, 22, 35, 23, 24, 25, 26, 27, 28, 29, 32, 30, 31, 33 }; string id; cin >> id; char letter = id[0]; int num = mapping[letter - 'A']; int a = num / 10; int b = num % 10; int sum = a + b * 9; for (int i = 1; i <= 9; i++) { int digit = id[i] - '0'; if (i <= 8) { sum += digit * (9 - i); } else { sum += digit; } } if (sum % 10 == 0) { cout << "real" << endl; } else { cout << "fake" << endl; } return 0; }
|
c531.:https://zerojudge.tw/ShowProblem?problemid=c531
難度:★★★☆☆
字串流應用、基本排序法、基本資料結構
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include <iostream> #include <string> #include <vector> #include <sstream> #include <algorithm>
using namespace std;
int main() { string line; while (getline(cin, line)) { stringstream ss(line); string token; vector<int> numbers; while (getline(ss, token, ',')) { numbers.push_back(stoi(token)); } vector<int> evens; for (int num : numbers) { if (num % 2 == 0) { evens.push_back(num); } } sort(evens.begin(), evens.end()); auto it = evens.begin(); for (size_t i = 0; i < numbers.size(); ++i) { if (numbers[i] % 2 == 0) { cout << *it; ++it; } else { cout << numbers[i]; } if (i < numbers.size() - 1) { cout << ","; } } cout << endl; } return 0; }
|
stoi():字串轉整數,string to int。
e446.:https://zerojudge.tw/ShowProblem?problemid=e446
難度:★☆☆☆☆
排列組合、列舉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <iostream> #include <algorithm> #include <vector>
using namespace std;
int main(){ ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; vector <int> nums; for (int i=1;i<=n;i++){ nums.push_back(i); } do{ for (int n : nums) cout << n << " "; cout << "\n"; } while(next_permutation(nums.begin(), nums.end())); return 0; }
|
最後一個測資點不知道是什麼鬼測資,測很久才發現 IO 要優化,記得別用 endl,用 ‘\n’ 取代。
至於 ios::sync_with_stdio(false), cin.tie(nullptr); 要不要加其實沒差,但如果加了可以少 0.3 秒左右。
d212.:https://zerojudge.tw/ShowProblem?problemid=d212
難度:★★☆☆☆
費氏數列、dp 優化
最簡單的解法就是遞迴解,但遞迴所花費的時間過多,在遞歸的時候會產生額外的計算開銷,也不會記錄答案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <iostream>
using namespace std;
int main() { int n; while(cin >> n) { if(n == 1) { cout << 1 << endl; continue; }
long long a = 1, b = 2, c; for(int i = 3; i <= n; i++) { c = a + b; a = b; b = c; } cout << b << endl; } return 0; }
|
此程式碼為 DP bottom-up(由下往上) 的方式:
主要先處理最小子問題:dp[1] = 1, dp[2] = 2(a = 1, b = 2),再用迴圈慢慢回推上去:dp[i] = dp[i-1] + dp[i-2],所以 i 從 3 開始。
時間複雜度:空間複雜度:
以下是使用 top-down(由上往下) 的處理方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <iostream> #include <vector>
using namespace std;
vector<long long> dp(100, -1);
long long ans(int n) { if (n == 1) return 1; if (n == 2) return 2;
if (dp[n] != -1) return dp[n];
return dp[n] = ans(n - 1) + ans(n - 2); }
int main() { int n; while (cin >> n) { cout << ans(n) << endl; } return 0; }
|
Top-Down 就跟 Bottom-Up 相反:
主要先拆解大問題,再用遞迴去求出小問題,最後透過 DP 儲存答案一步步求出最終解答。
另外 Top-Down 也強調記憶化(Memorization)的部分,因為遞迴會導致一些重複計算的部分而產生效能開銷,所以這時候 DP 的作用就發揮出來了。return dp[n] = ans(n-1) + ans(n-2) 的部分就是將答案記起來,就不用重複算了。
Top-Down 的時間複雜度:空間複雜度: