# APCS實作題2024年10月第1題:裝飲料
> 日期:2024年10月25日
> 作者:王一哲
> [ZeroJudge 題目連結](https://zerojudge.tw/ShowProblem?problemid=o711)
<br />
## 題目
### 問題描述
有一個杯子,可將其體積視為由兩個長方體組成(如下圖),下方的長方體底面積為 $w_1 \times w_1 ~\mathrm{cm^2}$,高為 $h_1 ~\mathrm{cm}$,上方的長方體底面積為 $w_2 \times w_2 ~\mathrm{cm^2}$,高為 $h_2 ~\mathrm{cm}$。
<img style="display: block; margin-left: auto; margin-right: auto" height="30%" width="30%" src="https://zerojudge.tw/ShowImage?id=4313">
<br />
一開始杯子為空。要裝 $n$ 次飲料,每一次裝 $v ~\mathrm{cm^3}$ 容量的飲料,當水杯滿時水位不再上升。問這 $n$ 次倒飲料中水位上升變化量最高是幾 cm。
<br />
### 輸入格式
第一行有一個正整數 $n$ 代表要裝 $n ~(1 \leq n \leq 10)$ 次飲料。接下來一行有 $4$ 個正整數 $w_1, w_2, h_1, h_2 ~(1 \leq w_1, w_2, h_1, h_2 \leq 50)$ 代表杯子的寬度與高度。最後一行有 $n$ 個正整數代表每次裝飲料的容量。保證每次水位上升都是整數。
子題配分
- 60%:$n = 1$,即答案為倒水後的高度
- 40%:無限制
<br />
### 輸出格式
輸出這 $n$ 次倒水中,上升變化量最大的高度為何。
<br />
### 範例輸入1
```
1
4 6 8 5
200
```
### 範例輸出1
```
10
```
### 範例輸入2
```
2
5 10 12 8
400 600
```
### 範例輸出2
```
13
```
### 範例輸入3
```
5
16 44 28 17
2560 1280 1536 1024 10448
```
### 範例輸出3
```
10
```
<br />
## Python 程式碼
費時最久約 21 ms,使用記憶體最多 3.3 MB,通過測試。
```python=
n = int(input()) # 倒飲料次數 n
w1, w2, h1, h2 = map(int, input().split()) # 底面寬度、高度
a1, a2 = w1*w1, w2*w2 # 下半部、上半部截面積
v1, v2 = a1*h1, a2*h2 # 下半部、上半部容積
data = list(map(int, input().split())) # n 次倒飲料的體積
imax, h, tot = 0, 0, 0 # 上升高度最大值、總高度、總體積
for d in data: # 依序由 data 讀取資料
dh = 0 # 這個倒飲料的高度變化
tot += d # 更新總體積
if tot <= v1: # 如果總體積小於等於 v1,倒入飲料後還在下半部
dh = d // a1 # 計算 dh
else: # 倒入飲料後已經在上半部
if h <= h1: # 原來在下半部
tmp = a1*(h1-h) # 於下半部的上升的高度
dh = (h1-h) + (d-tmp)//a2 # 加上於上半部上升的高度
else: # 已經在上半部
dh = d // a2 # 計算 dh
if tot >= v1 + v2: # 如果杯子已裝滿
dh = h1 + h2 - h
h += dh # 更新總高度
imax = max(imax, dh) # 更新最大值
# end of for loop
print(imax) # 印出最大值
```
<br /><br />
## C++ 程式碼
費時最久約 2 ms,使用記憶體最多 352 kB,通過測試。
```cpp=
#include <iostream>
using namespace std;
int main() {
ios::sync_with_stdio(0); cin.tie(0);
int n; cin >> n; // 倒飲料次數 n
int w1, w2, h1, h2; cin >> w1 >> w2 >> h1 >> h2; // 底面寬度、高度
int a1 = w1*w1, a2 = w2*w2; // 下半部、上半部截面積
int v1 = a1*h1, v2 = a2*h2; // 下半部、上半部容積
int data[n];
for(int i=0; i<n; i++) cin >> data[i]; // n 次倒飲料的體積
int imax =0, h = 0, tot = 0; // 上升高度最大值、總高度、總體積
for(int i=0; i<n; i++) { // 依序由 data 讀取資料
int dh = 0, d = data[i]; // 這次倒飲料的高度變化
tot += d; // 更新總體積
if (tot <= v1) { // 如果總體積小於等於 v1,倒入飲料後還在下半部
dh = d / a1; // 計算 dh
} else { // 倒入飲料後已經在上半部
if (h <= h1) { // 原來在下半部
int tmp = a1*(h1-h); // 於下半部的上升的高度
dh = (h1-h) + (d-tmp)/a2; // 加上於上半部上升的高度
} else { // 已經在上半部
dh = d / a2; // 計算 dh
}
if (tot >= v1 + v2) dh = h1 + h2 - h; // 如果杯子已裝滿
}
h += dh; // 更新總高度
if (dh > imax) imax = dh; // 更新最大值
}
cout << imax << "\n"; // 印出最大值
return 0;
}
```
<br /><br />
---
###### tags:`APCS`、`Python`、`C++`