---
# System prepended metadata

title: 2025/6 APCS 實作題

---

# 2025/6 APCS 實作題

# 第一題 - 小心陷阱
:::info
https://zerojudge.tw/ShowProblem?problemid=q836
:::


## 題目
在一維數線上進行一場模擬遊戲。遊戲規 則如下：
初始位置為0。
初始生命值為k（1 ≤ k ≤ 20）。
當前生命值為v時，角色會往右跳v格，也就是從位置p移動到p + v。
每次移動後，如果落在x1或x2的倍數上，會損失生命值：
若落在x1的倍數，生命值減少y1。
若落在x2的倍數，生命值減少y2。
若同時是x1和x2的倍數，生命值總共減少y1 + y2。
當生命值小於等於 0 時，遊戲結束，輸出當前所在的位置。

## 輸入說明:
輸入第一行 $k$ 表示初始生命值        
第二行有 $x1$ 與 $y1$
第三行有 $x2$ 與 $y2$
輸入範圍k：初始生命值，
1 ≤ k ≤ 20
x1、x2：兩個陷阱的倍數條件，
1 ≤ x1, x2 ≤ 10
y1、y2：對應陷阱的扣血值，
1 ≤ y1, y2 ≤ 20
子題
40% : $x1=3, x2=4, y1=y2=k$
60% : 無額外限制

## 輸出說明:
輸出遊戲結束所在的位置
## 解題絲路
```cpp=
'''
當前生命值為v時，角色會往右跳v格，也就是從位置p移動到p + v。
每次移動後，如果落在x1或x2的倍數上，會損失生命值：
若落在x1的倍數，生命值減少y1。
若落在x2的倍數，生命值減少y2。
若同時是x1和x2的倍數，生命值總共減少y1 + y2。
當生命值小於等於 0 時，遊戲結束，輸出當前所在的位置。
'''
#include <bits/stdc++.h>
#define io ios::sync_with_stdio;cin.tie(0);
using namespace std;

int main(){ io;
    int k;

    cin >> k;
    int x1,y1;
    cin >> x1>>y1;
    int x2,y2;
    cin >> x2>>y2;
    int tmp=k;

    int curr=0;

    while (k>0){
        if (tmp%x1==0 && tmp%x2==0){
            k-=y1;
            k-=y2;
        }else if (tmp%x2==0){
            k-=y2;
        }else if (tmp%x1==0){
            k-=y1;
        }
        curr=tmp;
        tmp+=k;
    }
    cout <<curr;
}
```
---
# 轉盤得分
2025/06 實作第二題
:::info
{%preview https://zerojudge.tw/ShowProblem?problemid=q837 %}
:::
# 題目
q837. 2.  轉盤得分 - 高中生程式解題系統

你有m個輪盤，每個輪盤上有n格，每格上寫有一個小寫英文字母（a~z）一場遊戲有k個回合。
       
每個輪盤的轉動可以是正數（順時針）、負數（逆時針）或 0（不轉）。

當所有輪盤都轉動完畢後，觀察它們
對齊位置上的字元。
對於每一個位置（從上到下的每一格），統計出現次數最多的字元，並將該字元的出現次數計 入分數。
每個回合的得分為這n格的對齊統計加總。
最終總得分為所有回合的得分總和。

> 範例
> 一開始有三個輪盤：apcsie, taiwan, icpeda，三個輪盤的轉動距離分別是：1 0 -4
> 結果：
> eapcsi   ← apcsie 右轉 1
> taiwan   ← 不動
> daicpe   ← icpeda 左轉 4

分數計算：
第一格: (e, t, d) 出現最多的字元出現 1 次
第二格: (a, a, a) 出現最多的字元出現 3 次
第三格: (p, i, i) 出現最多的字元出現 2 次
第四格: (c, w, c) 出現最多的字元出現 2 次
第五格: (s, a, p) 出現最多的字元出現 1 次
第六格: (i, n, e) 出現最多的字元出現 1 次
這次轉動後的分數是 $10 = 1+3+2+2+1+1$

## 輸入說明:
m n k
m 個長度 n 度小寫字母字串
k 行長度 m 的整數陣列表示轉動距離
m, n, k <= 30
-100 <= 轉動距離 <= 100
子題:
60%:  m = 3
40%: 無額外限制

## 輸出說明:
每個回合轉動後的分數總和

## 解題絲路
這種圓環旋轉，可以用rotate()來快速完成，但rotate只能左旋轉，如何實現右旋轉?
:::info
仔細觀察就可以發現左旋轉其實就是n-右旋轉步數
:::
```cpp=
#include <bits/stdc++.h>
#define io ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;

int main(){io;

    int m,n,k;
    cin >> m >> n >> k;

    vector<string> li(m);
    for (int i=0;i<m;++i)cin >> li[i];


    int ans=0;
    for (int i=0;i<k;++i){
        for (int j=0;j<m;++j){
            int mv;
            cin >> mv;
            
            int r;

            if (mv < 0) {
                r = abs(mv);
                r%=n;
                rotate(li[j].begin(), li[j].begin()+r, li[j].end());
            } else if (mv > 0) {
                r = n-(mv%n);
                rotate(li[j].begin(), li[j].begin()+r, li[j].end());
            }

        }
        for (int j=0; j<n; ++j) {
            array<int,26> cnt = {}; // 0 初始化
            for (auto &s : li) {
                cnt[s[j]-'a']++;
            }
            int mx = *max_element(cnt.begin(), cnt.end());
            ans += mx;
        }

    }

    cout << ans;
    return 0;
}
```
:::warning
需要注意題目有說旋轉步數會>n，所以要記得%=n，避免溢位
:::
## 解法2
二維陣列與deque的運用。
題目分兩步驟:
1. 旋轉
2. 計算得分

### 旋轉
其實就用deque把頭或尾取出，再放到對的地方就好

### 計算得分
用字典紀錄後再設mx不斷比大小
```cpp=
#include <bits/stdc++.h>
#define io ios::sync_with_stdio(0);cin.tie(0)
using namespace std;

void rotate(int n,deque<char>& q){
    if (n<0){
        n = abs(n);
        while (n != 0){ // 左轉(負數)
            char st = q.front();
            q.pop_front();
            q.push_back(st);
            n--;
        }
    }
    else{
        while (n != 0){
            char st = q.back();
            q.pop_back();
            q.push_front(st);
            n--;
        }
    }
}

int count(string& s){ // 尋找最多次字元出現幾次
    unordered_map<char,int> um;

    for (auto i:s){
        um[i]++;
    }
    int mx=0;
    for (auto p:um){
        mx = max(mx,p.second);
    }
    return mx;
};

int main(){io;
    int m=0,n=0,k=0,ans=0;

    cin >> m >>n>>k;
    vector<string> li(m);
    vector<vector<int>> move(k, vector<int>(m));// 宣告二維陣列的語法

    for (int i=0; i<m ;++i){
        cin >> li[i];
    }

    for (int x=0;x<k;++x){
        for (int y=0;y<m;++y){
            cin >> move[x][y];
        }
    }

    // 將 list資料寫進deque
    vector<deque<char>> Q(m); // queue<string>是錯誤的
    for (int a=0;a<m ;++a){
        for (auto i: li[a]){
            Q[a].push_back(i);
        }
    }
           
    int c=0,w=0;
    for (int x=0;x<k;++x){
        string s="";
        
        for (int y=0;y<m;++y){ // 執行旋轉的動作
            rotate(move[x][y],Q[y]);
        }

        for (w=0;w<n;++w){ // 計算此輪分數
            for (c=0;c<m;++c){
                s+=Q[c][w];
            }
            ans+=count(s);
            s = "";
        }
    }

    cout << ans ;
    return 0;
}
```

---

:::info
趁機宣傳一下我自己的個人網站跟Youtube頻道 !!

**[個人網站](https://hyc.eshachem.com/) | [Youtube頻道](https://www.youtube.com/@Hy.C)**
:::
@2025 Hy.C 陳毓
> Copyright ©Hy.C 陳毓 CC BY-NC-SA 4.0 | 禁止商業用途 | 轉載標記出處 | 改編作品必須在相同條款下分享。