# 2024/10 APCS 實作題
# 第一題 - 裝飲料
:::info
https://zerojudge.tw/ShowProblem?problemid=o711
:::
## 題目
有一個杯子,可將其體積視為由兩個長方 體組成(如下圖),下方的長方體底面積 為 $w_1 \times w_1$ cm$^2$,高為 $h_1$ cm,上方的長方體底面積為 $w_2 \times w_2$ cm$^2$,高為 $h_2$ cm。
一開始杯子為空。要裝 $n$ 次飲料,每一次裝 $v$ cm$^3$ 容量的飲料,當水杯滿 時水位不再上升。問這 $n$ 次倒飲料中水位上升變化量最高是幾 cm。
## 輸入說明:
第一行有一個正整數 $n (1 \le n \le 10)$ 代表要裝 $n$ 次飲料。接下來一行有 4 個正整數 $w_1, w_2, h_1, h_2 (1 \le w_1, w_2, h_1, h_2 \le 50)$ 代表杯子的寬度與高度。最後一行有 $n$ 個正整數代表每次裝飲料的容量。保證每次水位上 升都是整數。
(60%) n = 1,即答案為倒水後的高度
(40%) 無限制
## 輸出說明:
輸出這 $n$ 次倒水中,上升變化量最大的高度為何。
## 解題絲路
說實話其實我一開始根本看不懂題目...講來講去到底要幹嘛還是不清楚,光是讀懂題目就花了一段時間...
白話文:
杯子的體積是一大一小兩個長方形體積相加,連續倒n次水,哪次會使水位升高最多(溢出的就不算)。
>
> 以測資2舉例:
> 第一次倒 400:水位從 0 → 13(上升 13)
> 第二次倒 600:水位從 13 → 19(上升 6)
> 輸出13。
所以想法其實很簡單,就只有三種情況:
1. **V<=G1**: 如果此時倒水體積(V)小於小長方體(G1),那增加的高度就只有 $(V/G1)\times h1$
2. **G1<=V<=G2+G1**: 如果此時的體積(V)大於G1卻小於G2,則增加高度為$h1 + ((V-G1)/G2)\times h2$
3. **G1+G2<V**: 如果此時的體積(V)大於G1+G2也就是大於整個杯子,則水會溢出來,$h1 + h2$
```cpp=
#include <bits/stdc++.h>
#define io ios::sync_with_stdio(0);cin.tie(0);
using namespace std;
int main(){
int n;
cin >> n;
double w1,w2,h1,h2;
cin >> w1>> w2>>h1>>h2;
double G1 = w1*w1*h1;
double G2 = w2*w2*h2;
double mx=0,V=0,H=0;
for (int i=0;i<n;++i){
double a;
cin >> a;
double oldH=H;
V+=a;
if (V <= G1)H=V/G1*h1;
else if (V <= G1 + G2) H = h1 + (V - G1) / G2*h2;
else H=h1+h2;
mx = max(mx, H-oldH);
}
cout << mx;
}
```
:::warning
因為C++除法的特性,所以建議都用double。
:::
# 第二題 - 蒐集寶石
2024/10 實作第二題
:::info
題目:
{%preview https://zerojudge.tw/ShowProblem?problemid=o712 %}
:::
# 題目
有一個 $M \times N$ 的地圖,每一格的數字紀錄著寶石的數量,如果數字是 -1 代表牆壁。
有一位機器人一開始位於 $(r, c)$ 的位置上且方向朝右邊,他遵循著以下規則行走。
1. 若機器人位於的格字內寶石數量為 $0$,則機器人程式終止。
2. 機器人維護著一個分數 score,將 score 加上當前格的寶石數量,並且撿起一顆寶石。
3. 若 score 是 $k$ 的倍數,則向右轉 90 度。
4. 若機器人面向的格子是牆壁或是超出邊界,則繼續向右轉 90 度直到面向的格子非牆壁或非超出邊界,並回到第 1 步。
例如機器人一開始在座標 $(2, 1)$ 且 $k = 2$,向右走兩步之後分數為 $3 + 2 + 3 = 8$, 由於 $8$ 是 $2 (k = 2)$ 的倍數所以向右轉 $90$ 度。接下來往下走一步分數變為 $11$,需要向右轉 $2$ 次 $90$ 度才不會面向牆壁或是邊界外的格子。
接下來向前走一步走到座標 $(2, 3)$,由於先前已經拿走一顆寶石,該位置的寶石數量變為 $2$,因此分數變為 $13$,再繼續往上走兩步到 $(0, 3)$ 處分數為 $16$,由於 $16$ 為 $2 (k = 2)$ 的倍數所以向右轉 $90$ 度。
向前走一格到 $(0, 4)$ 後需要向右轉兩次 $90$ 度,回到 $(0, 3)$ 後由於寶石數量為 $0$ ,機器人停止。過程中機器人總共撿了 $8$ 顆寶石。
## 輸入說明:
第一行有 $5$ 個正整數 $M, N, k, r, c$
$1 \le M \le 100$
$2 \le N \le 100$
$1 \le k \le 20$
$0 \le r < m$
$0 \le c < n$
保證機器人初始位置不是牆壁。接下來有 $M$ 行,每一行有 $N$ 的數字,代表地圖的資訊。
(60%) M = 1
(40%) 無限制
## 輸出說明:
輸出機器人會蒐集幾個寶石。
---
格狀圖的應用,只要記得下面這幾件事:
1. 用moves代表移動,dir來實現移動。
2. 結束條件多-> 用另一個函式來判斷是否符合結束條件。
3. 因為要一直執行,用無限迴圈。
4. 用原生array建立格狀圖
## 初步格式
```cpp=
# include <bits/stdc++.h>
# define io ios::sync_with_stdio(0),cin.tie(0);
using namespace std;
int graph[101][101] ={};
int moves[4][2]={{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
int end(){} // 如果要結束就回傳 1
int main(){io;
memset(graph,-1,sizeof(graph));
// 因為有預留牆壁的位置所以迴圈從1開始跑
for (int i=1;i<=M;++i){
for (int j=1;j<=N;++j){
cin >> graph[i][j];
}
}
int score=0,gem=0;
while(true){
if (end())break;
if (!(score%k))dir=(dir+1)%4;
}
return 0;
}
```
:::warning
要注意因為有給牆壁留空間,所以起始位置各要++
:::
**轉彎規則如下:**
1.score是k倍數。
2.面向牆壁要無條件一直轉,直到不是面向牆壁。
所以除了上面程式寫到的`if (!(score%k))dir=(dir+1)%4;`,我們還ˊ需要另一個while來一直判斷此時是否面向牆壁。
## 解
```cpp=
# include <bits/stdc++.h>
# define io ios::sync_with_stdio(0),cin.tie(0);
using namespace std;
int graph[102][102] ={};
int moves[4][2]={{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
int end(int r,int c){
if (graph[r][c]==0)return 1;
int ok=4;
for (int i=0;i<4;i++) //判斷四面是否都是牆壁
if (graph[r+moves[i][0]][c+moves[i][1]] == -1)
ok--;
if (ok == 0) //四面都是牆壁
return 1;
return 0;
}
int main(){io;
int M,N,k,r,c;
cin >> M >> N >> k>>r>>c;
memset(graph,-1,sizeof(graph));
// 因為有預留牆壁的位置,所以起始位置要++
r++;
c++;
for (int i=1;i<=M;++i){
for (int j=1;j<=N;++j){
cin >> graph[i][j];
}
}
int score=0,gem=0,dir=0;
while (true){
if (end(r,c))break;
score+=graph[r][c];
graph[r][c]--;
gem+=1;
if (!(score%k))dir=(dir+1)%4;
int temp_r,temp_c;
while (true){
// 如果現在的方向是面對牆壁,要轉到正確的方向
temp_r = r+moves[dir][0];
temp_c = c+moves[dir][1];
if (graph[temp_r][temp_c]==-1)dir=(dir+1)%4;
else break;
}
r = temp_r;
c = temp_c;
}
cout << gem;
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 | 禁止商業用途 | 轉載標記出處 | 改編作品必須在相同條款下分享。