4月15阿里筆試程式設計題口糊
阿新 • • 發佈:2022-04-15
20分鐘ak,但前面選擇基本全忘了(((
\(A\):簽到
\(B\):對每個非'.'位置上、下、左斜上、右斜下方向分別去check4個是否相同即可
\(C\):n<=2000,考慮樹形揹包:
- 對於每個點,其子樹之間必沒有父子關係,求每個點所有子樹之間的答案取min就是最終答案
- 每個點所有節點的值組成一個集合,這個集合是可以dfs去dp的
但\(a_i<=1000(應該是?), n<=2000\),開陣列去存集合不太行,並且求答案需要比較快速。所以對於每個點,開了個set放入已經check完的所有子樹,把沒check的子樹中的點\(x\)在這個set裡lower_bound拿到相對近的值的指標,再prev一下,拿到這兩個值(如果存在)與x做差取絕對值然後對ans取min,最後按子樹順序把子樹插入到check完了的集合裡面。(寫的好抽象,看程式碼即可)
#include<bits/stdc++.h> using namespace std; #define ll long long int v[2005]; vector<int>G[2005]; int ans = 1e9; set<int> dfs(int from, int fa) { set<int>now; for (auto& to : G[from]) { if (to == fa)continue; auto tmp = dfs(to, from); v[from] += v[to]; for (auto i : tmp) { auto p = now.lower_bound(i); if (p != now.end()) { ans = min(ans, abs(*p - i)); } if (p != now.begin()) { ans = min(ans, abs(*prev(p) - i)); } } for (auto i : tmp) now.insert(i); } now.insert(v[from]); return now; } int main() { int n; cin >> n; for (int i = 1; i <= n; i++) { cin >> v[i]; } for (int i = 1; i < n; i++) { int x, y; cin >> x >> y; G[x].push_back(y); G[y].push_back(x); } dfs(1, 0); cout << ans; return 0; }
總結:暴力即可