1. 程式人生 > 其它 >4月15阿里筆試程式設計題口糊

4月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;
}

總結:暴力即可