# 2022年10月APCS題解 ## P1巴士站牌 [題目](https://zerojudge.tw/ShowProblem?problemid=i428) >初階教學: 沒什麼好講的,照題序打 ```cpp= #include<bits/stdc++.h> using namespace std; #define x first #define y second vector<pair<int, int> > vc(200); int main(){ int n; cin >> n; for(int i = 0; i < n; i++){ cin >> vc[i].x; cin >> vc[i].y; } int maxn = 0; int minn = INT_MAX; for(int i = 0; i < n - 1; i++){ maxn = max(maxn,abs(vc[i].x - vc[i+1].x) + abs(vc[i].y - vc[i+1].y)); minn = min(minn,abs(vc[i].x - vc[i+1].x) + abs(vc[i].y - vc[i+1].y)); } cout << maxn << ' ' << minn << '\n'; } ``` ## 運貨站 [題目](https://zerojudge.tw/ShowProblem?problemid=j123) >初階教學: 實作題,每種方塊都是從最外面一格一格向內推,如果撞到東西了,就更新陣列,然後break,輸入下一個。 最後在跑過一輪看有多少位置沒有被更新過。 A B C D E的code都差不多,就只有判斷和更新一點點不一樣 >by進階助教 >不能用向外推的方式 >會爛掉的側資: >1 1 1 0 0 0 1 0 0 0 1 0 0 0 1 0 C 1 ```cpp= #include<bits/stdc++.h> using namespace std; int arr[1000][1000]; int main(){ int r, c, n; cin >> r >> c >> n; int blank = 0, out = 0; for(int i = 0; i < r; i++){ arr[i][0] = 1; } while(n--){ char cc; cin >> cc; int t; cin >> t; if(cc == 'A'){ for(int i = c; i >= 0; i--){ if(arr[t][i] or arr[t+1][i] or arr[t+2][i] or arr[t+3][i]){ if(i < c){ arr[t][i+1] = 1; arr[t+1][i+1] = 1; arr[t+2][i+1] = 1; arr[t+3][i+1] = 1; } else{ out++; } break; } } } if(cc == 'B'){ for(int i = c; i >= 0; i--){ if(arr[t][i]){ if(i + 3 <= c){ arr[t][i+1]=1; arr[t][i+2]=1; arr[t][i+3]=1; } else{ out++; } break; } } } if(cc == 'C'){ for(int i = c; i >= 0; i--){ if(arr[t][i] or arr[t+1][i]){ if(i+2 <= c){ arr[t][i+1] = 1; arr[t][i+2] = 1; arr[t+1][i+1] = 1; arr[t+1][i+2] = 1; } else{ out++; } break; } } } if(cc == 'D'){ for(int i = c; i >= 0; i--){ if(arr[t+1][i] or arr[t][i+2]){ if(i + 3 <= c){ arr[t+1][i+1]=1; arr[t+1][i+2]=1; arr[t+1][i+3]=1; arr[t][i+3] = 1; } else{ out++; } break; } } } if(cc == 'E'){ for(int i = c; i >= 0; i--){ if(arr[t][i+1] or arr[t+1][i] or arr[t+1][i+1] or arr[t+2][i] or arr[t+2][i+1]){ if(i+2 <= c){ arr[t][i+2] = 1; arr[t+1][i+1] = 1; arr[t+1][i+2] = 1; arr[t+2][i+1] = 1; arr[t+2][i+2] = 1; } else{ out++; } break; } } } // for(int i = 0; i < r; i++){ // for(int j = 0; j <= c; j++){ // cout << arr[i][j] ; // }cout << '\n'; // } } for(int i = 0; i < r; i++){ for(int j = 1; j <= c; j++){ if(!arr[i][j])blank++; } } cout << blank << ' ' << out << '\n'; } ``` ## 石窟探險 [題目](https://zerojudge.tw/ShowProblem?problemid=j124) >初階教學: 用DFS跟著探險家走,輸入偶數就向下DFS兩個叉路,基數就三個,0就回傳,並在DFS傳值時傳上一個節點的值,只要現在的節點不是0就可以把兩個差加入ans中 (這題節點數*節點值的大小會爆int,所以記得開long long) ```cpp= #include<bits/stdc++.h> #define int long long using namespace std; int ans = 0; bool flag = 1; void dfs(int p){ int x; cin >> x; if(flag){ ans -= x; flag = 0; } ans += abs(p - x); if(x == 0){ ans -= abs(p - x); return; } if(x % 2 == 0){ dfs(x); dfs(x); return; } else if(x % 2 == 1){ dfs(x); dfs(x); dfs(x); return; } } signed main(){ dfs(0); cout << ans << '\n'; } ``` >進階教學: 照著題目做 ```cpp= #include<bits/stdc++.h> using namespace std; typedef long long ll; vector< int > tree; void add_node(int n) { tree.emplace_back( n ); tree.emplace_back( n ); if( n & 1 ) tree.emplace_back( n ); } int main () { ll ans = 0, n; cin >> n; add_node(n); while( cin >> n ) { if( n!=0 ) ans += abs(tree.back()-n); tree.pop_back(); if( n!= 0) add_node(n); } cout << ans; } ``` > frankie: ```cpp= #include <bits/stdc++.h> #define V vector #define sz size() #define pb push_back #define em empty() using LL = long long; using namespace std; constexpr int N=1e6+1; V < V<int> > vec(N,V<int>()); LL ans=0; V <int> v; void dfs(const int &cur){ v.pb(cur); for (const int &i:vec[cur]) if (i) dfs(i); if (v.sz>1) return ans+=abs(v.back()-v[v.sz-2]),v.pop_back(); return v.pop_back(); } int main(){ cin.tie(nullptr); ios::sync_with_stdio(false); int n,root; stack <int> sk; cin >> root,sk.push(root); while (cin >> n){ vec[sk.top()].pb(n); if (n) sk.push(n); while (!sk.em&&vec[sk.top()].sz==2+(sk.top()&1)) sk.pop(); if (sk.em) break; } dfs(root),cout << ans; return 0; } ``` ## 蓋步道 [題目](https://zerojudge.tw/ShowProblem?problemid=j125) 這題就是二分搜加上BFS 單調性:只要小的高度可以走,那麼大的就一定可以 所以我們用這個單調性做二分搜 然後用BFS做每次二分搜時的檢查 ```cpp= #include<bits/stdc++.h> #define int long long using namespace std; int n; int v[500][500]; int h[500][500]; struct qq{ int x; int y; int step; qq(){x = 1;y = 1; step = 0;} }; queue<qq> q; void clear(queue<qq>& q){ queue<qq> empty; swap(q,empty); } int BFS(int hh){ clear(q); v[1][1] = 1; qq t;q.push(t); while(!q.empty()){ qq now = q.front(); q.pop(); if(now.x > n or now.y > n)cout << "test" << '\n'; //cout << "xy" << now.x << ' ' << now.y << '\n'; if(now.x == n && now.y == n){ return now.step; } if(now.x < n) if(abs(h[now.x + 1][now.y] - h[now.x][now.y]) <= hh && !v[now.x + 1][now.y]){ qq tmp; tmp.x = now.x + 1;tmp.y = now.y;tmp.step = now.step + 1; v[now.x+1][now.y] = 1; //cout << "txy" << tmp.x << ' ' << tmp.y << '\n'; q.push(tmp); } if(now.y < n) if(abs(h[now.x][now.y + 1] - h[now.x][now.y]) <= hh && !v[now.x][now.y + 1]){ qq tmp; tmp.x = now.x; tmp.y = now.y + 1;tmp.step = now.step + 1; v[now.x][now.y + 1] = 1; //cout << "txy" << tmp.x << ' ' << tmp.y << '\n'; q.push(tmp); } if(now.x > 1) if(abs(h[now.x-1][now.y] - h[now.x][now.y]) <= hh && !v[now.x - 1][now.y]){ qq tmp; tmp.x = now.x - 1; tmp.y = now.y;tmp.step = now.step + 1; v[now.x - 1][now.y] = 1; //cout << "txy" << tmp.x << ' ' << tmp.y << '\n'; q.push(tmp); } if(now.y > 1) if(abs(h[now.x][now.y - 1] - h[now.x][now.y]) <= hh && !v[now.x][now.y - 1]){ qq tmp; tmp.x = now.x; tmp.y = now.y - 1;tmp.step = now.step + 1; v[now.x][now.y - 1] = 1; //cout << "txy" << tmp.x << ' ' << tmp.y << '\n'; q.push(tmp); } } return -1; } signed main(){ cin >> n; for(int i = 1; i <= n; i++){ for(int j = 1; j <= n; j++){ cin >> h[i][j]; } } int l = 0, r = 1e6+1; int m,k; int anss; while((r > l)){ m = (l + r) >> 1; //cout << l <<' '<< m <<' '<< r << '\n'; k = BFS(m); memset(v,0,sizeof(v)); //cout << k <<'\n'; if(k == -1){ l = m + 1; } if(k != -1){ r = m; anss = k; } } cout << l << '\n' << anss << '\n'; } // 0 0 1 ``` <!-- > 進階教學 ```cpp= #include<bits/stdc++.h> using namespace std; int ar[ 302 ][ 302 ]; bool vis[ 302 ][ 302 ]; int N; int dx[ 4 ] = {0, 0, 1, -1}; int dy[ 4 ] = {1, -1, 0, 0}; struct pnt { int x, y, len; pnt( int _x, int _y, int _len ) : x(_x), y(_y), len(_len){} ; pnt(){} ; }; int bfs( int m ) { memset( vis, 0, sizeof(vis) ); queue<pnt> qq; qq.emplace(1, 1, 0); while( !qq.empty() ) { auto a = qq.front(); qq.pop(); if( vis[ a.x ][ a.y ] ) continue; if( a.x == N && a.y == N ) return a.len; vis[ a.x ][ a.y ] = true; for( int i = 0; i < 4; ++i ) { int nx = a.x + dx[i]; int ny = a.y + dy[i]; if( nx < 1 || nx > N ) continue; if( ny < 1 || ny > N ) continue; if( vis[ nx ][ ny ] ) continue; if( abs(ar[ nx ][ ny ] - ar[ a.x ][ a.y ]) > m ) continue; qq.emplace( nx, ny, a.len+1 ); } } return -1; } int main () { cin >> N; for( int i = 1; i <= N; ++i ) for( int j = 1; j <= N; ++j ) cin >> ar[i][j]; int l = -1, r = 1e6+1; while( r-l > 1 ) { int m = (l+r+1)/2; int ans = bfs( m ); if( ans == -1 ) l = m; else r = m; } cout << l+1 << '\n' << bfs(l+1) << '\n'; } ``` >frankie解: ```cpp= #include <bits/stdc++.h> #define V vector using namespace std; const int N = 1e6, S = 301; struct path {int x, y, sl, len;}; int mnm, n; V < V<int> > vec; void modify(queue <path> &q, const int &x, const int &y, const int &sl, const int &len, const int &lim){ path p; if (sl <= lim){ p.x = x; p.y = y; p.sl = sl; p.len = len; q.push(p); } } bool judge(const int &lim) { V < V<bool> > vst(S,V<bool>(S)); queue <path> q; path p; p.x = p.y = p.sl = p.len = 0; q.push(p); while (!q.empty()){ int x=q.front().x, y=q.front().y, sl=q.front().sl, len=q.front().len; q.pop(); if (x == n && y == n){ mnm = len; return true; } if (vst[y][x]) continue; vst[y][x] = true; len++; if (x) modify(q, x-1, y, max( abs(vec[y][x] - vec[y][x - 1]), sl) , len, lim); if (x != n) modify(q, x+1, y, max( abs(vec[y][x] - vec[y][x + 1]), sl), len, lim); if (y) modify(q, x, y-1, max( abs(vec[y][x] - vec[y - 1][x]), sl) , len, lim); if (y != n) modify(q, x, y+1, max( abs(vec[y][x] - vec[y + 1][x]), sl), len, lim); } return false; } int main(){ cin.tie(nullptr); ios::sync_with_stdio(false); int l=0, r=-1, len; cin >> n; vec.assign(n,V<int>(n)); n--; for (auto &i: vec) for (int &j: i) cin >> j, r = max(r, j); for (int mid = (l + r) >> 1; ; mid = (l + r) >> 1) if (l == mid) break; else if (judge(mid)) r = mid,len = mnm; else l = mid; if (!judge(l)) l++; cout << l << endl << len; return 0; } ``` -->