大概刷了 50 題左右 GPE Helper 上面比較常出現的題目,根據題目類型分類做一些筆記,方便之後複習。
Map
Problem
UVA
10579 Hay Points
10295
10520 Conformity
11286
Array
Problem
UVA
21964 Fill the Containers
11413
23551 Largest Square
10908
10437 Zeros and Ones
10324
暴力法
Problem
UVA
10655 Sumsets
10125
10417 The Hotel with Infinite Rooms
10170
22351 Quirksome Squares
256
Map
Hay Points
UVA 10295
題目大意
首先會列出數個單字以及其所對應的價值,之後會有幾段文字,根據文字中出現的單字計算其總價值,如果單字沒有寫出其對應價值,代表價值為 0。
解題方法
使用 Map
儲存列出的單字以及其價值,之後遍歷整段文字,利用 count
判斷單字的價值並加總。
注意事項
程式碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include <bits/stdc++.h> using namespace std;int m, n, k;string str; map<string, int > dict; int main () { cin >> m >> n; while (m--){ cin >> str >> k; dict[str] = k; } while (n--){ int c = 0 ; while (cin >> str && str != "." ){ if (dict.count (str) != 0 ) c += dict[str]; } cout << c << endl; } return 0 ; }
UVA 11286
題目大意
輸入包含若干行,每行有五個數字代表學生修習的課程,找到最多人選擇的課程組合有幾個學生選擇,如果有兩個或以上的組合有相同數量的學生選擇,則將他們的選擇人數相加。
解題方法
將輸入的五個課程排序之後作為 Map
的 key,並且每次更新 Map
時紀錄最多人選擇的組合有幾人選擇,之後利用 iterator
遍歷 Map
統計人數。
也可以選擇將課程排序之後轉為 string
並作為 Map
的 key。
注意事項
程式碼
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 <bits/stdc++.h> using namespace std;int n;vector<int > v (5 ) ;int main () { while (cin >> n && n != 0 ){ map<vector<int >, int > m; int ma = -1 , c = 0 ; while (n--){ for (int i = 0 ; i < 5 ; i++){ cin >> v[i]; } sort (v.begin (), v.end ()); if (m.count (v) != 0 ) m[v]++; else m[v] = 1 ; if (m[v] > ma) ma = m[v]; } for (auto i = m.begin (); i != m.end (); i++){ if (i->second == ma) c += (i->second); } cout << c << endl; } return 0 ; }
Array
Fill the Containers
UVA 11413
題目大意
有好幾瓶不同容量的牛奶,現在要將其重新分配到幾個瓶子中,每瓶牛奶只能裝到一個瓶子中,不能分配到好幾個瓶子裡,而且只能按照牛奶的順序進行分配,求分配後最大容量的瓶子所需的最小值。
ex:
3 瓶牛奶容量分別為 4, 78, 9
,分配到 2 瓶子中,最大容量的瓶子最少需要 4 + 78 = 82
,不能分成 4 + 9, 78
因為這樣沒有按照順序。
解題方法
使用二分搜尋,每次判斷是否能夠滿足分配規則,不能滿足就把數字放大,否則把數字縮小,直到找到最小的容量。
注意事項
程式碼
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 #include <bits/stdc++.h> using namespace std;int n, m;vector<int > v (1000 ) ;bool check (int x, int n, int m) { int c = 0 , tmp = 0 ; for (int i = 0 ; i < n; i++){ if (tmp + v[i] > x){ if (v[i] > x) return false ; tmp = v[i]; c++; }else tmp += v[i]; } return (c + 1 <= m); } int main () { while (cin >> n >> m){ int l = 1 , r = 0 ; for (int i = 0 ; i < n; i++){ cin >> v[i]; r += v[i]; } while (r > l){ int mid = (l + r) / 2 ; if (check (mid, n, m)) r = mid; else l = mid + 1 ; } cout << l << endl; } return 0 ; }
Largest Square
UVA 10908
題目大意
給定一個二維矩陣,裡面包含不同字母,之後輸入一個座標,求以該座標為中心的同字母正方形之最大邊長。
解題方法
由中心開始,每次往外檢查一圈,直到出現不同的字母就停下。
注意事項
程式碼
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 #include <bits/stdc++.h> using namespace std;int solve (vector<vector<char >> v, int r, int c) { int i = 1 ; char t = v[r][c]; for (; i < max (v.size (), v[0 ].size ()); i++){ if (r + i >= v.size () || r - i < 0 || c + i >= v[0 ].size () || c - i < 0 ) break ; int j = 0 ; for (; j < i * 2 ; j++){ if (v[r + i][c - i + j] != t || v[r + i - j][c + i] != t || v[r - i][c + i - j] != t || v[r - i + j][c - i] != t) break ; } if (j != i * 2 ) break ; } return i * 2 - 1 ; } int t, m, n, q, r, c;int main () { cin >> t; while (t--){ cin >> m >> n >> q; cout << m << " " << n << " " << q << endl; vector<vector<char >> v (m, vector <char >(n)); for (int i = 0 ; i < m; i++){ for (int j = 0 ; j < n; j++){ cin >> v[i][j]; } } while (q--){ cin >> r >> c; cout << solve (v, r, c) << endl; } } return 0 ; }
Zeros and Ones
UVA 10324
題目大意
給定一個由 0
和 1
組成的字串,之後會有數個查詢,每次查詢一個範圍內的數字是否都是相同的,如果範圍內都是同樣的 0
或是 1
則返回正確,否則返回錯誤。
解題方法
另外建立一個陣列儲存前綴和,並利用區間的數字總和判斷區間內是否都是 0
或是 1
。
注意事項
程式碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <bits/stdc++.h> using namespace std;string str; int c = 1 , q, a, b;int main () { while (cin >> str){ cout << "Case " << c << ":" << endl; c++; vector<int > v (str.size() + 1 , 0 ) ; for (int i = 0 ; i < str.size (); i++){ v[i + 1 ] = v[i] + (str[i] - '0' ); } cin >> q; while (q--){ cin >> a >> b; if (v[a] == v[b + 1 ] || v[a] + b - a + 1 == v[b + 1 ]) cout << "Yes" << endl; else cout << "No" << endl; } } return 0 ; }
暴力法
有些題目看似需要去想一些演算法來處理,實際上數字範圍不大,可以直接用暴力的方式去解。
Sumsets
UVA 10125
題目大意
給定一串數字,在這些數字中取出四個不重複數字,使得 a + b + c = d
,求出最大可能的 d
。
解題方法
將數字排序之後,由大到小將數字做為 d
並檢查,如果滿足條件則退出。
更好的作法可以解 a + b = d - c
。
注意事項
程式碼
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 #include <bits/stdc++.h> using namespace std;int n;int main () { while (cin >> n && n != 0 ){ if (n < 4 ){ cout << "no solution" << endl; continue ; } vector<int > v (n) ; for (int i = 0 ; i < n; i++){ cin >> v[i]; } sort (v.begin (), v.end ()); int ans = INT_MIN; for (int d = n - 1 ; d >= 0 ; d--){ for (int c = 0 ; c < n; c++){ if (c == d) continue ; for (int b = c + 1 ; b < n; b++){ if (b == d) continue ; for (int a = b + 1 ; a < n; a++){ if (a == d) continue ; if (v[a] + v[b] + v[c] == v[d]){ ans = v[d]; break ; } } if (ans != INT_MIN) break ; } if (ans != INT_MIN) break ; } if (ans != INT_MIN) break ; } if (ans != INT_MIN) cout << ans << endl; else cout << "no solution" << endl; } return 0 ; }
The Hotel with Infinite Rooms
UVA 10170
題目大意
有一間有無限房間的飯店,並且有好幾團旅客依照特定的規則入住:每一團都比前一團多住一天,並且每次只會有一團旅客入住,現在給定第一團旅客所住的天數,求第 n
天是第幾團旅客正在住。
解題方法
不斷累加旅客所住的時間,直到超過所求天數 n
為止。
程式碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include <bits/stdc++.h> using namespace std;long long s, d;int main () { while (cin >> s >> d){ long long c = 0 ; for (int i = s;;i++){ c += i; if (c >= d){ cout << i << endl; break ; } } } return 0 ; }
Quirksome Squares
UVA 256
題目大意
有一種特殊的數字 x
有 2n
位數,可以分成兩個 n
位數 a、b
,並且滿足 a 2 + b 2 = x a^2 + b^2 = x a 2 + b 2 = x ,ex: 3 0 2 + 2 5 2 = 3025 30^2 + 25^2 = 3025 3 0 2 + 2 5 2 = 3 0 2 5 ,每次會輸入一個數字 2n
,求出所有 2n
位數的特殊數字。
解題方法
接收輸入前先把 2, 4, 6, 8
位數的表先建立好,其實就是遍歷範圍內的數字做檢查。
注意事項
程式碼
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 <bits/stdc++.h> using namespace std;vector<vector<int >> v (4 , vector <int >()); int n, d[4 ] = {10 , 100 , 1000 , 10000 };int main () { for (int k = 0 ; k < 4 ; k++){ for (int i = 0 ; i < d[k]; i++){ for (int j = 0 ; j < d[k]; j++){ if ((i + j) * (i + j) == (i * d[k] + j)){ v[k].push_back ((i + j) * (i + j)); } } } } while (cin >> n){ for (int i = 0 ; i < v[n / 2 - 1 ].size (); i++){ if (n == 2 ) printf ("%02d\n" , v[0 ][i]); else if (n == 4 ) printf ("%04d\n" , v[1 ][i]); else if (n == 6 ) printf ("%06d\n" , v[2 ][i]); else printf ("%08d\n" , v[3 ][i]); } } return 0 ; }