# APCS實作題2025年6月第2題:轉盤得分 > 日期:2025年6月26日 > 作者:王一哲 > [ZeroJudge 題目連結](https://zerojudge.tw/ShowProblem?problemid=q837) <br /> ## 題目 ### 問題描述 你有 $m$ 個輪盤,每個輪盤上有 $n$ 格,每格上寫有一個小寫英文字母(a ~ z)。一場遊戲有 $k$ 個回合。 每個回合,每個輪盤會基於上一個回合結束的狀態做轉動,然後計算當前狀態的得分: 1. 每個輪盤的轉動可以是正數(順時針)、負數(逆時針)或 0(不轉)。 2. 當所有輪盤都轉動完畢後,觀察它們對齊位置上的字元。 3. 對於每一個位置(從上到下的每一格),統計出現次數最多的字元,並將該字元的出現次數計入分數。 4. 每個回合的得分為這 $n$ 格的對齊統計加總。 最終總得分為所有回合的得分總和。 **範例** 一開始有三個輪盤:apcsie, taiwan, icpeda,三個輪盤的轉動距離分別是:1 0 -4 結果: 1. eapcsi ← apcsie 右轉 1 2. taiwan ← 不動 3. daicpe ← icpeda 左轉 4 分數計算: 1. 第一格: (e, t, d) 出現最多的字元出現 1 次 2. 第二格: (a, a, a) 出現最多的字元出現 3 次 3. 第三格: (p, i, i) 出現最多的字元出現 2 次 4. 第四格: (c, w, c) 出現最多的字元出現 2 次 5. 第五格: (s, a, p) 出現最多的字元出現 1 次 6. 第六格: (i, n, e) 出現最多的字元出現 1 次 這次轉動後的分數是 $10 = 1+3+2+2+1+1$ <br /> ### 輸入格式 第一行為 m n k 接下來有 m 行長度為 n 的小寫字母字串 最後 k 行為長度 m 的整數陣列,表示轉動距離 其中 - $m, n, k \leq 30$ - $-100 \leq 轉動距離 \leq 100$ 子題配分 - 60%: $m = 3$ - 40%:無額外限制 <br /> ### 輸出格式 每個回合轉動後的分數總和 <br /> ### 範例一:輸入 ``` 3 6 2 apcsie taiwan icpeda 1 0 -4 7 -3 2 ``` ### 範例一:正確輸出 ``` 17 ``` ### 範例二:輸入 ``` 4 3 3 abc bab cbc abc -1 -6 -6 -7 5 -3 4 0 -7 4 2 8 ``` ### 範例二:正確輸出 ``` 21 ``` <br /> ### 評分說明 <br /><br /> ## Python 程式碼 ### 寫法1,用串列切片模擬每次轉動後輪盤的狀態 使用時間約為 35 ms,記憶體約為 3.7 MB,通過測試。 ```python= from collections import defaultdict m, n, k = map(int, input().split()) # m 個輪盤,n 格,k 回合 roulettes = [list(input()) for _ in range(m)] # 讀取輪盤資料 score = 0 # 分數 for _ in range(k): # 讀取 k 回合轉動格數 rotates = list(map(int, input().split())) # 轉動格數 for i in range(m): # 依序讀取輪盤與轉動格數 rotate = rotates[i] if rotate > 0: # 順時鐘方向轉,資料向後平移 rotate %= n # 對 n 取餘數 roulettes[i] = roulettes[i][n-rotate:] + roulettes[i][:n-rotate] elif rotate < 0: # 逆時鐘方向轉,資料向前平移 rotate = -rotate # 轉回正值 rotate %= n # 對 n 取餘數 roulettes[i] = roulettes[i][rotate:] + roulettes[i][:rotate] for i in range(n): # 讀取每一格的字母 cnt = defaultdict(int) # 計數器 for roulette in roulettes: # 讀取每一個輪盤 cnt[roulette[i]] += 1 score += max(cnt.values()) # 加上同一個字母出現次數最大值 print(score) ``` <br /> ### 寫法2,記錄每次轉動後的起點位置 使用時間約為 38 ms,記憶體約為 3.7 MB,通過測試。 ```python= from collections import defaultdict m, n, k = map(int, input().split()) # m 個輪盤,n 格,k 回合 roulettes = [list(input()) for _ in range(m)] # 讀取輪盤資料 starts = [0]*m # 輪盤的起點 score = 0 # 分數 for _ in range(k): # 讀取 k 回合轉動格數 for i, step in enumerate(map(int, input().split())): # 轉動格數 if step > 0: # 順時鐘方向轉,資料向後平移 starts[i] += n - step%n elif step < 0: # 逆時鐘方向轉,資料向前平移 step = -step # 轉回正值 starts[i] += step%n for i in range(n): # 讀取每一格的字母 cnt = defaultdict(int) # 計數器 for j, roulette in enumerate(roulettes): # 讀取每一個輪盤 cnt[roulette[(i+starts[j])%n]] += 1 # 索引值要加上起點位置再對 n 取餘數 score += max(cnt.values()) # 加上同一個字母出現次數最大值 print(score) ``` <br /><br /> ## C++ 程式碼 ### 寫法1,用 rotate 模擬每次轉動後輪盤的狀態 這個寫法速度較慢,使用時間約為 12 ms,記憶體約為 352 MB,通過測試。 ```cpp= #include <iostream> #include <iostream> #include <vector> #include <string> #include <map> #include <algorithm> using namespace std; int main() { ios::sync_with_stdio(0); cin.tie(0); int m, n, k; cin >> m >> n >> k; // m 個輪盤,n 格,k 回合 vector<string> roulettes (m); // 輪盤資料 for(int i=0; i<m; i++) cin >> roulettes[i]; int score = 0; // 分數 for(int i=0; i<k; i++) { // 讀取 k 回合轉動格數 for(int j=0; j<m; j++) { // 依序讀取輪盤與轉動格數 int step; cin >> step; if (step > 0) { // 順時鐘方向轉,資料向後平移 step %= n; // 對 n 取餘數 int d = n - step; // 起點平移的距離 rotate(roulettes[j].begin(), roulettes[j].begin()+d, roulettes[j].end()); } else if (step < 0) { // 逆時鐘方向轉,資料向前平移 step = -step; // 轉回正值 step %= n; // 對 n 取餘數 rotate(roulettes[j].begin(), roulettes[j].begin()+step, roulettes[j].end()); } } for(int j=0; j<n; j++) { // 讀取每一格的字母 map<char, int> cnt; // 計數器 for(auto roulette : roulettes) { // 讀取每一個輪盤 cnt[roulette[j]]++; } int imax = 0; // 出現次數最大值 for(auto it : cnt) imax = max(imax, it.second); score += imax; // 加上同一個字母出現次數最大值 } } cout << score << "\n"; return 0; } ``` <br /> ### 寫法2,記錄每次轉動後的起點位置 使用時間約為 5 ms,記憶體約為 352 kB,通過測試。 ```cpp= #include <iostream> #include <string> #include <map> using namespace std; int main() { ios::sync_with_stdio(0); cin.tie(0); int m, n, k; cin >> m >> n >> k; // m 個輪盤,n 格,k 回合 string roulettes[m]; // 輪盤資料 for(int i=0; i<m; i++) cin >> roulettes[i]; int starts[m] = {0}, score = 0; // 輪盤的起點,分數 for(int i=0; i<k; i++) { // 讀取 k 回合轉動格數 for(int j=0; j<m; j++) { // 依序讀取輪盤與轉動格數 int step; cin >> step; if (step > 0) { // 順時鐘方向轉,資料向後平移 starts[j] += n - step%n; } else if (step < 0) { // 逆時鐘方向轉,資料向前平移 step = -step; // 轉回正值 starts[j] += step%n; } } for(int j=0; j<n; j++) { // 讀取每一格的字母 map<char, int> cnt; // 計數器 for(int t=0; t<m; t++) { // 讀取每一個輪盤 cnt[roulettes[t][(j + starts[t]) % n]]++; } int imax = 0; // 出現次數最大值 for(auto it : cnt) imax = max(imax, it.second); score += imax; // 加上同一個字母出現次數最大值 } } cout << score << "\n"; return 0; } ``` <br /><br /> --- ###### tags:`APCS`、`C++`、`Python`