APCS 11110 (實作題) === https://drive.google.com/drive/folders/1XLeCHTzrrf1Io9wZ2IPWAJylZp2ZeDyr [toc] :::info **TODO**: - 講解題目 - 題目標題 - 題目意思 - 輸入輸出例子 - 子題分數範圍 & 時間限制 - 題目敘述 - 至少寫三個 sample testcase - 說明 sample testcase - 生測資 - assert 輸入輸出範圍 - 說明每筆測試資料要測試什麼 case - 上架 Zerojudge - 題目敘述 - 測試資料 ::: ## P1 巴士站距離 ???sec :::info ::: ### 題目 :::info 輸入座標範圍 [-100, 100] subtask - 50% - 50% ::: 第一題 給 n 個二維座標(4<=n<=100) 求第 i 個和第 i+1 個座標的曼哈頓距離的最大&最小值 有 平面上有 $n$ 個巴士站,第 $i$ 個巴士站的位置可以用座標點 $(x_i, y_i)$ 來表示。 兩個巴士站之間行進的時間是這兩個巴士站座標的曼哈頓距離。曼哈頓距離的定義如下: 對於兩個座標點 $(x_1, y_1)$ 與 $(x_2, y_2)$,兩點之間曼哈頓距離的為 $|x_1-x_2| + |y_1 - y_2|$。 你今天要從的巴士站 $1$ 坐車到巴士站 $n$,中間依序經過巴士站 $2, 3, 4, \cdots, (n-1)$。 請計算過程中相鄰兩站的行進時間的 **最大值** 與 **最小值**。 ### 輸入格式 第 1 行有一個正整數 $n$ 表示路程中總共會經過幾個巴士站 在輸入的第 $2$ 行到第 $n+1$ 行,每行有兩個整數標示巴士站的座標。 嚴格的說,輸入第 $i+1$ 行的兩個數字依序是 $x_i$ 和 $y_i$。 子題配分: $(60\%)$:$n = 4 $ 且 $-100 \leq x_i, y_i \leq 100$ $(60\%)$:$2 \leq n \leq 100$ 且 $-100 \leq x_i, y_i \leq 100$ ### 輸出格式 在一行輸出兩個整數並以空格分開。 第一個整數表示相鄰兩站的行進時間的**最大值**。 第二個整數表示相鄰兩站的行進時間的**最小值**。 **sample 1** ``` Inpuuuuuuuuuut 1 4 1 1 1 3 4 5 2 6 ``` ``` Outpuuuuuuuuut 1 5 2 ``` **sample 2** ``` Inpuuuuuuuuuut 2 3 1 2 -1 -1 1 3 ``` ``` Outpuuuuuuuuut 2 6 5 ``` ### note #### 範例 1 #### 範例 2 ### 子題 #### 1-10 (60%) ./gen 4 1 ./gen 4 2 ./gen 4 3 ./gen 4 4 ./gen 4 5 ./gen 4 6 ./gen 4 7 ./gen 4 8 ./gen 4 9 ./gen 4 10 #### 11 4 100 100 -100 -100 0 0 0 0 #### 12 4 -100 100 100 -100 3 3 -3 -3 #### 13-20 ./gen 100 13 ./gen 100 14 ./gen 100 15 ./gen 100 16 ./gen 100 17 ./gen 100 18 ./gen 100 19 ./gen 100 20 ## P2 運貨站 ???sec :::info task 1: 只有 OOO 的 task 2: 圖片上排三種 task 3: ::: ### 題目 第二題 奇怪的模擬題 有 n 個可以分為五種不同形狀的東西 依序推進一個 R*C 的倉庫裡 等等補形狀 R<=30 C<=50 n<=200 一開始都在右邊,每次給一個東西的右上角的 y 座標,要往左邊推,直到不同移動為止。 輸出有幾個格子沒有被填滿 ![](https://i.imgur.com/3MMSFBs.png) ![](https://i.imgur.com/qLPlTDp.png) ### 輸入格式 R C N A y1 ### 輸出格式 **sample 1** ``` Inpuuuuuuuuuut 1 ``` 5 4 5 B 1 B 2 B 4 B 2 B 4 ``` Outpuuuuuuuuut 1 11 2 剩下 11 個格子2個物件不能放進去 [0, 0] ~ [R-1, C-1] ``` **sample 2** ``` Inpuuuuuuuuuut 2 ``` ``` Outpuuuuuuuuut 2 ``` ### note #### 範例 1 #### 範例 2 ```cpp= #include <bits/stdc++.h> using namespace std; int r, c; array<int, 5> Ly = {3, 0, 1, 1, 2}, Lx = {0, 2, 1, 2, 1}; array<array<int, 34>, 54> D; int push(int x, int y, int t){ for(; x; x--){ if(t == 0 && (D[x][y] || D[x][y - 1] || D[x][y - 2] || D[x][y - 3])) break; else if(t == 1 && D[x][y]) break; else if(t == 2 && (D[x][y] || D[x][y - 1])) break; else if(t == 3 && (D[x][y] || D[x + 2][y - 1])) break; else if(t == 4 && (D[x][y] || D[x][y - 1] || D[x + 1][y - 2])) break; } x++; if(x + Lx[t] > c) return 1; if(t == 0) D[x][y] = D[x][y - 1] = D[x][y - 2] = D[x][y - 3] = 1; else if(t == 1) D[x][y] = D[x + 1][y] = D[x + 2][y] = 1; else if(t == 2) D[x][y] = D[x][y - 1] = D[x + 1][y] = D[x + 1][y - 1] = 1; else if(t == 3) D[x][y] = D[x + 1][y] = D[x + 2][y] = D[x + 2][y - 1] = 1; else D[x][y] = D[x][y - 1] = D[x + 1][y] = D[x + 1][y - 1] = D[x + 1][y - 2] = 1; return 0; } signed main(){ int n, y, up = 0, sum = 0; char t; cin >> r >> c >> n; for(int i = 1; i <= n; i++){ cin >> t >> y, y += 1 + Ly[t - 'A']; up += push(c, y, t - 'A'); } for(int i = 1; i <= c; i++){ for(int j = 1; j <= r; j++){ sum += !D[i][j]; cout << D[i][j] << " "; } cout << "\n"; } cout << sum << " " << up << "\n"; return 0; } ``` #### sample 1 ``` 3 4 3 B 0 B 0 B 1 ``` ``` 6 1 ``` #### sample 2 ``` 5 6 3 C 3 D 4 A 4 ``` ``` 18 0 ``` #### sample 3 ``` 5 6 3 E 5 E 4 D 2 ``` ``` 16 0 ``` ##### note ``` 0 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0 1 0 0 1 1 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0 1 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 16 0 ``` #### sample 5 ![](https://i.imgur.com/2qWBCND.png) ``` 5 6 6 C 4 A 4 E 5 E 5 A 5 B 5 ``` ##### note ``` put C at 4 0 0 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 put A at 4 0 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 put E at 5 0 0 0 0 1 0 1 1 1 1 1 0 1 1 1 1 1 0 0 0 1 0 0 0 0 0 1 0 0 0 put E at 5 (failed) 0 0 0 0 1 0 1 1 1 1 1 0 1 1 1 1 1 0 0 0 1 0 0 0 0 0 1 0 0 0 put A at 5 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 0 0 1 0 0 1 0 0 0 put B at 5 (failed) 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 0 0 1 0 0 1 0 0 0 13 2 ``` ### 子題 (20%) ./gen 1 20 40 200 1 ./gen 1 20 40 200 2 ./gen 1 20 40 200 3 ./gen 1 30 50 200 81 (40%) ./gen 2 30 50 200 4 ~ 11 (40%) ## P3 石窟探險 ???sec :::info 序列長度 10^6 ::: 編號 0 是死路 編號 [0, 100000] 石室數量不超過 [100000] 深度不超過 40 Time Limit Python 3s other 1s 第三題 現在有一棵樹,偶數號節點有兩個邊,奇數號節點有三個邊,有人從根開始依序走左(中)右三條邊做DFS 然後給你走完的序列(0代表走下去的是死路)要你算每個節點與子節點的差的絕對值總和 深度 < 40 ### 題目 ### 輸入格式 2 0 0 0 ### 輸出格式 **sample 1** ``` Inpuuuuuuuuuut 1 ``` 2 6 0 8 14 0 0 0 10 0 4 0 0 ``` Outpuuuuuuuuut 1 26 ``` **sample 2** ``` Inpuuuuuuuuuut 2 5 2 10 0 0 0 8 0 0 17 0 0 0 0 6 0 0 ``` ``` Outpuuuuuuuuut 2 29 ``` ### note #### 範例 1 #### 範例 2 ### 子題 ```cpp= #include <bits/stdc++.h> #define int long long #define pb push_back using namespace std; int p = 0, sum = 0; vector<int> V; int DFS(){ int u = V[p++], v; if(!u) return 0; for(int i = 0; i < 2 + (u % 1); i++){ v = DFS(); if(v) sum += abs(u - v); } return u; } signed main(){ int v; while(cin >> v) V.pb(v); DFS(); cout << sum << "\n"; return 0; } ``` p3 generator ```cpp= #include <algorithm> #include <cassert> #include <cstdlib> #include <ctime> #include <deque> #include <iostream> #include <random> #include <vector> using namespace std; const int M = 100005; vector<int> g[M]; deque<int> que; void push(int x) { que.push_back(x); int i = rand() % que.size(); swap(que[i], que.back()); } int pop() { assert(que.size() > 0); int x = que.front(); que.pop_front(); return x; } int root; void dfs(int x) { if (x != root) cout << ' '; cout << x; if (x == 0) return; assert((int)g[x].size() == 2 + x % 2); for (int v : g[x]) { dfs(v); } } int main() { srand(clock()); vector<int> p; for (int i = 1; i <= 100000; i++) p.push_back(i); std::random_device rd; std::mt19937 rg(rd()); shuffle(p.begin(), p.end(), rg); push(p[0]); push(p[0]); if (p[0] % 2) push(p[0]); int n = 1000 - rand() % 2; for (int i = 1; i < n; i++) { int u = p[i]; int par = pop(); g[par].push_back(u); // cout << "par(" << u << ")=" << par << endl; push(u); push(u); if (u % 2) push(u); } for (int i = 0; i < M; i++) { while ((int)g[i].size() < 2 + i % 2) { g[i].push_back(0); } shuffle(g[i].begin(), g[i].end(), rg); } root = p[0]; dfs(root); return 0; } ``` ## P4 蓋步道 ???sec :::info 子題配分? n 的大小 Python 4s C++ Java 1s 20%, n<=10, 高度 value <=10 20%, n<=300, 高度 value <=1000 60%, n<=300, 高度 <= 10^6 ::: ### 題目 第四題 給一個 n\*n 的表格,表格上有不大於 1e6 的數字,然後你要找一條從左上走到右下的最短路徑,並讓該路徑上相鄰兩數的差的絕對值的最大值最小 ### 輸入格式 n matrix ### 輸出格式 **sample 1** ``` 4 9 4 3 2 5 9 8 10 3 3 2 8 6 3 3 4 ``` ``` Outpuuuuuuuuut 1 ``` **sample 2** ``` Inpuuuuuuuuuut 2 ``` ``` Outpuuuuuuuuut 2 ``` :::danger TODO p4 輸入移除行尾空格 ::: ### note 我發現我給你的測資忘了輸出路徑長 #### 範例 1 #### 範例 2 ### 子題 ```cpp= #include <bits/stdc++.h> using namespace std; int dx[] = {0, 1, 0, -1}; int dy[] = {1, 0, -1, 0}; using pii = pair<int, int>; int bfs(int M, auto &vec) { int n = vec.size(); auto vis = vector<vector<int>>(n, vector<int>(n, -1)); vis[0][0] = 0; queue<pii> q; q.emplace(0, 0); while (q.size()) { auto [x, y] = q.front(); q.pop(); for (int d = 0; d < 4; d++) { int nx = x + dx[d]; int ny = y + dy[d]; if (nx < 0 or nx >= n or ny < 0 or ny >= n) continue; if (vis[nx][ny] != -1) continue; if (abs(vec[x][y] - vec[nx][ny]) > M) continue; vis[nx][ny] = vis[x][y] + 1; q.emplace(nx, ny); } } return vis[n - 1][n - 1]; } int main() { cin.tie(0)->sync_with_stdio(0); int n; cin >> n; auto vec = vector<vector<int>>(n, vector<int>(n)); for (auto &vv : vec) for (auto &v : vv) cin >> v; int L = -1, R = 1e6 + 5; while (R - L > 1) { int M = (L + R) / 2; (bfs(M, vec) != -1 ? R : L) = M; } cout << R << '\n'; cout << bfs(R, vec) << '\n'; } ```