# APCS 20221023 題解
## 第一題:巴士站牌 [(題目敘述)](https://zerojudge.tw/ShowProblem?problemid=i428)
* 此題只需邊輸入邊用abs取相鄰兩站之間的距離,然後找出最大值和最小值即可(Example 1)
* 一開始我看成要找出每個站之間的距離才用以下的辦法(用pair <int, int> p[] 存座標) (Example 2)
* #還以為第一題難度什麼時候(進步)那麼快
:::spoiler Example 1
```cpp=
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, x, y, px, py, Max = -INT_MAX, Min = INT_MAX;
cin >> n >> px >> py;
for(int i=0; i<n-1; i++){
cin >> x >> y;
int dis = abs(x - px) + abs(y - py);
Max = max(Max, dis);
Min = min(Min, dis);
px = x, py = y;
}
cout << Max << ' ' << Min;
}
```
:::
:::spoiler Example 2
```cpp=
#include <bits/stdc++.h>
using namespace std;
int main() {
pair <int, int> p[10000];
vector <int> save;
int n;
cin >> n;
for(int i=0; i<n; i++){
cin >> p[i].first >> p[i].second;
}
for(int i=0; i<n-1; i++){
save.push_back(abs(p[i].first - p[i+1].first) + abs(p[i].second - p[i+1].second));
}
cout << *max_element(save.begin(), save.end()) << ' ' << *min_element(save.begin(), save.end());
}
```
:::
## 第二題:運貨站 [(題目敘述)](https://zerojudge.tw/ShowProblem?problemid=j123)
* now[] 用來記錄每一列當前的長度
:::spoiler Example
```cpp=
#include <bits/stdc++.h>
using namespace std;
int now[35];
int r, c, n, place, ans1 = 0, ans2 = 0; //ans1:進倉庫的格子數 ans2:進倉庫貨物數量
char box;
void A(int x){
int Max = -1;
for(int i=x; i<=x+3; i++) Max = max(Max, now[i]);
if(Max + 1 < c){
ans1 += 4;
ans2++;
for(int i=x; i<=x+3; i++) now[i] = Max + 1;
}
}
void B(int x){
if(now[x] + 3 < c) {
ans1 += 3;
ans2++;
now[x] += 3;
}
}
void C(int x){
int Max = max(now[x], now[x+1]);
if(Max + 2 < c){
ans1 += 4;
ans2++;
for(int i=x; i<=x+1; i++) now[i] = Max + 2;
}
}
void D(int x){
if(now[x] + 1 < c && now[x+1] + 3 < c) {
ans1 += 4;
ans2++;
if(now[x] + 1 >= now[x+1] + 3 ){
now[x]++;
now[x+1] = now[x];
}
else{
now[x+1] += 3;
now[x] = now[x+1];
}
}
}
void E(int x){
if(now[x] + 1 < c && now[x+1] + 2 < c && now[x+2] + 2 < c) {
ans1 += 5;
ans2++;
if(now[x] + 1 >= now[x+1] + 2 && now[x] + 1 >= now[x+2] + 2){
now[x]++;
now[x+1] = now[x];
now[x+2] = now[x];
}
else if(now[x+1] + 2 >= now[x] + 1 && now[x+1] + 2 >= now[x+2] + 2){
now[x+1] += 2;
now[x] = now[x+1];
now[x+2] = now[x+1];
}
else{
now[x+2] += 2;
now[x] = now[x+2];
now[x+1] = now[x+2];
}
}
}
int main() {
memset(now, -1, sizeof(now));
cin >> r >> c >> n;
for(int i=0; i<n; i++){
cin >> box >> place;
if(box == 'A') A(place);
else if(box == 'B') B(place);
else if(box == 'C') C(place);
else if(box == 'D') D(place);
else if(box == 'E') E(place);
}
cout << r*c - ans1 << ' ' << n - ans2;
}
```
:::
## 第三題:石窟探險[(題目敘述)](https://zerojudge.tw/ShowProblem?problemid=j124)
* 直接用題目已經跑完整個樹的節點來做DFS (Example 1)
* * 先整理題目用stack做一個樹,再做DFS遍歷 (較為複雜) (Example 2)
:::spoiler Example 1
```cpp=
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
vector <ll> v;
ll n, now = 0, ans = 0;
ll DFS(){
ll next, t = v[now++];
if(t){
for(int i=0; i<2 + (t%2) ? 1 : 0; i++){
next = DFS();
if(next) ans += abs(t - next);
}
return t;
}
else return 0;
}
int main() {
while(cin >> n) v.push_back(n);
DFS();
cout << ans;
}
```
:::
:::spoiler Example 2
```cpp=
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a, root = 0, ans = 0;
stack <ll> pre;
vector <ll> v[100005];
bool check(){
if(pre.top() % 2 && v[pre.top()].size() == 3) return true;
else if(pre.top() % 2 == 0 && v[pre.top()].size() == 2) return true;
else return false;
}
void dfs(ll x){
for(int i=0; i<v[x].size(); i++){
if(v[x][i] != 0){
ans += abs(x - v[x][i]);
dfs(v[x][i]);
}
}
}
int main() {
cin >> a;
root = a;
pre.push(a);
while(cin >> a){
v[pre.top()].push_back(a);
if(a != 0){
pre.push(a);
}
else{
while(check()){
pre.pop();
if(pre.size() == 0) break;
}
}
}
dfs(root);
cout << ans;
}
```
:::
## 第四題: 蓋步道[(題目敘述)](https://zerojudge.tw/ShowProblem?problemid=j125)
* 二分搜高度
* 用BFS來驗證是否能到終點以及到終點的最短距離
:::spoiler Example
```cpp=
#include <bits/stdc++.h>
using namespace std;
int n, arr[350][350] , bfs[350][350];
int ans1 = 0, ans2 = 0;
int BFS(int x){
int sx = 1, sy = 1, Max = -1;
queue <pair<int, int>> q;
q.push({sx, sy});
while(q.size()){
int a = q.front().first;
int b = q.front().second;
q.pop();
if(bfs[a+1][b] == 0 && abs(arr[a+1][b] - arr[a][b]) <= x){
Max = max(Max, abs(arr[a+1][b] - arr[a][b]));
q.push({a+1, b});
bfs[a+1][b] = bfs[a][b] + 1;
}
if(bfs[a][b+1] == 0 && abs(arr[a][b+1] - arr[a][b]) <= x){
Max = max(Max, abs(arr[a][b+1] - arr[a][b]));
q.push({a, b+1});
bfs[a][b+1] = bfs[a][b] + 1;
}
if(bfs[a-1][b] == 0 && abs(arr[a-1][b] - arr[a][b]) <= x){
Max = max(Max, abs(arr[a-1][b] - arr[a][b]));
q.push({a-1, b});
bfs[a-1][b] = bfs[a][b] + 1;
}
if(bfs[a][b-1] == 0 && abs(arr[a][b-1] - arr[a][b]) <= x){
Max = max(Max, abs(arr[a][b-1] - arr[a][b]));
q.push({a, b-1});
bfs[a][b-1] = bfs[a][b] + 1;
}
}
if(bfs[n][n] != 0) {
ans1 = Max;
ans2 = bfs[n][n] - 1;
return 1;
}
else return 0;
}
void reset(){
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
bfs[i][j] = 0;
}
}
}
int main() {
cin >> n;
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
cin >> arr[i][j];
}
}
int L = 0, R = 1000000;
while(L < R - 1){
memset(bfs, -1, sizeof(bfs));
reset();
bfs[1][1] = 1;
int M = (L + R) / 2;
if(BFS(M) == 0) L = M;
else R = M;
}
cout << ans1 << '\n' << ans2;
}
```
:::