# APCS實作題2024年1月第1題:遊戲選角
> 日期:2024年1月29日
> 作者:王一哲
> 題目來源:2024年1月實作題第1題
> [ZeroJudge 題目連結](https://zerojudge.tw/ShowProblem?problemid=m931)
## 題目
### 問題描述
有 $n$ 個角色,每個角色有攻擊力和防禦力。
角色的能力值是攻擊力和防禦力的平方和,輸出能力值第二大的攻擊力和防禦力數值。
保證每個角色的能力值相異。
<br />
### 輸入說明
第一行包含一個整數 $n (3 \leq n \leq 20)$,表示有多少個角色。
接下來的 $n$ 行,每行包含兩個整數 $a_i$ 和 $d_i$,表示第 $i$ 個角色的攻擊力和防禦力。
子題分數:
- 60%:滿足 $n=3$。
- 40%:一般情況。
<br />
### 輸出格式
輸出兩個整數,表示能力值第二大的角色的攻擊力和防禦力。
<br />
### 範例輸入1
```
3
3 1
5 2
1 4
```
### 範例輸出1
```
1 4
```
<br />
### 範例輸入2
```
6
6 6
1 3
8 6
5 4
2 8
7 2
```
### 範例輸出2
```
6 6
```
<br />
### 範例輸入3
```
5
34 35
84 32
39 79
59 89
59 31
```
### 範例輸出3
```
84 32
```
<br />
## Python 程式碼
### 方法1,暴力解,計算每一項的平方和再由大到小排序
因為每一筆測資最多只有20項,暴力解也不會超時。費時約為 27 ms,使用記憶體約為 3.3 MB,通過測試。
```python=
n = int(input()) # 讀取角色人數 n
# 讀取接下來 n 行的角色數值,轉成整數存入串列 data,第4、5行有一樣的效果
data = [list(map(int, input().split())) for i in range(n)]
#for i in range(n):
# data.append(list(map(int, input().split())))
# 計算每個角色的能力值平方和,再由大到小排序
data.sort(reverse=True, key=lambda x : x[0]*x[0] + x[1]*x[1])
print("{:d} {:d}".format(data[1][0], data[1][1])) # 印出答案
```
<br />
### 方法2,計算每一項的平方和,記錄目前最大的兩個值
速度沒有比暴力解快。費時約為 31 ms,使用記憶體約為 3.3 MB,通過測試。
```python=
n = int(input()) # 讀取角色人數 n
# 讀取接下來 n 行的角色數值,轉成整數存入串列 data
data = [list(map(int, input().split())) for i in range(n)]
first, second = [-1, -1], [-1, -1] # 目前最大的兩個值,內容為 [能力值, 索引值]
for i, d in enumerate(data): # 依序讀取 data 的資料
val = d[0]*d[0] + d[1]*d[1] # 計算能力值平方和 val
if val >= first[0]: # 如果 val 大於 first[0]
second = first # second 更新為目前的 first
first = [val, i] # first 更新為 [val, i]
elif val >= second[0]: # 如果 val 小於 first[0]、大於 second[0]
second = [val, i] # second 更新為 [val, i]
print("{:d} {:d}".format(data[second[1]][0], data[second[1]][1])) # 印出答案
```
<br />
## C++ 程式碼
### 方法1,暴力解,計算每一項的平方和再由大到小排序
因為每一筆測資最多只有20項,暴力解也不會超時。費時約為 2 ms,使用記憶體約為 324 kB,通過測試。
```cpp=
#include <iostream>
#include <vector>
#include <utility> // for pair
#include <algorithm> // for sort
using namespace std;
int main() {
int n; cin >> n; // 讀取角色人數 n
vector<pair<int, int>> data; // 儲存角色能力值的 vector,內容為 pair
for(int i=0; i<n; i++) { // 讀取 n 個角色的資料
int a, d; cin >> a >> d; // 攻擊力存入 a,防禦力存入 d
data.push_back({a, d}); // 將 {a, d} 加入 data
}
/* 使用 lambda function 作為比較式,由能力值平方和由大到小排序 */
sort(data.begin(), data.end(), [](pair<int, int> x, pair<int, int> y) {
return x.first*x.first + x.second*x.second > y.first*y.first + y.second*y.second;
});
cout << data[1].first << " " << data[1].second << "\n"; // 印出答案
return 0;
}
```
<br />
### 方法2,計算每一項的平方和,記錄目前最大的兩個值
方法1使用了比較多奇特的工具,方法2只使用基本的工具解題。速度沒有比暴力解快。費時約為 2 ms,使用記憶體約為 328 kB,通過測試。
```cpp=
#include <iostream>
using namespace std;
int main() {
int n; cin >> n; // 讀取角色人數 n
int data[n][2]; // 儲存角色能力值的 array,內容為 {a, d}
for(int i=0; i<n; i++) { // 讀取 n 個角色的資料
int a, d; cin >> a >> d; // 攻擊力存入 a,防禦力存入 d
data[i][0] = a; // 將 {a, d} 存入 data
data[i][1] = d;
}
int first[2] = {-1, -1}, second[2] = {-1, -1}; // 目前最大的兩個值,內容為 [能力值, 索引值]
for(int i=0; i<n; i++) { // 依序讀取 data 的資料
int a = data[i][0], d = data[i][1]; // 攻擊力存入 a,防禦力存入 d
int val = a*a + d*d; // 計算能力值平方和
if (val >= first[0]) { // 如果 val 大於 first[0]
second[0] = first[0]; // second 更新為目前的 first
second[1] = first[1];
first[0] = val; // first 更新為 {val, i}
first[1] = i;
} else if (val >= second[0]) { // 果 val 小於 first[0]、大於 second[0]
second[0] = val; // second 更新為 {val, i}
second[1] = i;
}
}
cout << data[second[1]][0] << " " << data[second[1]][1] << "\n"; // 印出答案
return 0;
}
```
<br /><br />
---
###### tags:`APCS`、`Python`、`C++`