2018 Benelux Algorithm Programming Contest (BAPC 18)

2018 Benelux Algorithm Programming Contest (BAPC 18)

A - A Prize No One Can Win

int main() {
    IOS; cin >> n >> m; VI a(n); k = 1;
    for (auto &i : a) cin >> i; sort(all(a));
    rep (i, 1, n - 1) if (a[i] + a[i - 1] <= m) ++k;
    cout << k;
    return 0;
}

B - Birthday Boy

int c[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
char s[25];

int calc(PII a, PII b) {
    int ans = b.se - 1 - a.se + (a.fi == b.fi ? 0 : c[a.fi]);
    rep(i, a.fi + 1, b.fi - 1) ans += c[i];
    return ans;
}

int main() {
    scanf("%d", &n); vector<PII> a(n);
    for (auto& i : a) scanf("%s %d-%d", s, &i.fi, &i.se); sort(all(a));
    int x = a[0].fi, y = a[0].se - 1, k = calc(a.back(), { 12, 31 }) + calc({ 1, 1 }, a[0]) + 2;
    if (!y) x = x == 1 ? 12 : x - 1, y = c[x];
    rep(i, 1, n - 1) {
        int cur = calc(a[i - 1], a[i]), cx = a[i].fi, cy = a[i].se - 1;
        if (!cy) cx = cx == 1 ? 12 : cx - 1, cy = c[cx];
        if (cur > k || (cur == k && PII{ x, y } <= PII{ 10, 27 } && PII{ cx, cy } > PII{10, 27}))
            k = cur, x = a[i].fi, y = a[i].se - 1;  
    }
    if (x < 10) cout << 0; cout << x << '-';
    if (y < 10) cout << 0; cout << y;
    return 0;
}

C - Cardboard Container

int main() {
    IOS; cin >> n; ans = 2 + n * 4;
    rep (c, 1, n) {
        rep (h, 1, c) {
            if (c * h > n) break;
            if (n % (c * h) == 0) umin(ans, c * h + n / h + n / c << 1);
        }
    }
    cout << ans;
    return 0;
}

F - Financial Planning

二分, 注意再循环的时候一旦成功就跳出, 否则会爆ll

int main() {
    IOS; cin >> n >> m; vector<PLL> a(n);
    for (auto &i : a) cin >> i.fi >> i.se;
    ll l = 1, r = 2e9;
    while (l < r) {
        ll mid = l + r >> 1;
        ll ans = 0;
        for (auto &p : a) {
            ans += max(0ll, p.fi * mid - p.se);
            if (ans >= m) break;
        }
        if (ans >= m) r = mid;
        else l = mid + 1;
    }
    cout << l;
    return 0;
}

G - Game Night

最终序列是ABC的全排列, 起点任意, 干脆最终状态为 ABC 或者 ACB

然后通过滑动窗匹配就行了

int c[3];
string s, t[3], a, b;

int work(string& s, string& t, string a) {
    int ans = 0, cnt = 0;
    rep (i, 0, n - 1) cnt += s[i] != t[i]; ans = cnt;
    rep (i, 0, n - 2) {
        if (s[i] == a[0]) ++cnt;
        if (s[i + c[a[0] - 'A']] == a[0]) --cnt;
        if (s[i + c[a[0] - 'A']] == a[1]) ++cnt;
        if (s[i + c[a[0] - 'A'] + c[a[1] - 'A']] == a[1]) --cnt;
        if (s[i + c[a[0] - 'A'] + c[a[1] - 'A']] == a[2]) ++cnt;
        if (s[i + c[a[0] - 'A'] + c[a[1] - 'A'] + c[a[2] - 'A']] == a[2]) --cnt;
        umin(ans, cnt);
    }
    return ans;
}

int main(){
    IOS; cin >> n >> s;
    for (auto i : s) ++c[i - 'A']; s += s;
    rep (i, 0, 2) string(c[i], 'A' + i).swap(t[i]);
    a = t[0] + t[1] + t[2], b = t[0] + t[2] + t[1];
    cout << min(work(s, a, "ABC"), work(s, b, "ACB"));
    return 0;
}

I - In Case of an Invasion, Please...

最小化值, 想二分, 找到可用边, 然后网络流

但复杂度必炸, 注意到最多10个避难点

最多有 1 << 10 种状态, 复杂度就够了

把能到达完全相同数量和编号的点合并, 最多有1024种,

s 向 这1024状态连边, 1024在向 避难点 连边, 避难点在向 t 连边

相当与我们实在二分这1024种状态到避难点的最小最大长度, 那最多有 1024 * 10条边

排序二分边的序号即可

const int N = 1e5 + 15, M = 2e4 + 5;
const ll inf = 1ll << 60;

int n, m, _, k;
int a[N];
ll dis[11][N], sum;
bool v[N];
PII sh[11];
vector<PII> e[N];

void dij(int s, ll* d) {
    memset(v, 0, sizeof v);
    priority_queue<pair<ll, int>> q; q.push({d[s] = 0, s});
    while (!q.empty()) {
        int x = q.top().se; q.pop();
        if (v[x]) continue; v[x] = 1;
        for (auto &y : e[x]) if (d[y.fi] > d[x] + y.se)
            q.push({-(d[y.fi] = d[x] + y.se), y.fi});
    }
}

int h[1050], ne[M], to[M], tot, now[1050];
int d[1050], s = 1025, t = 1026;
ll co[M], st[1050];

void add(int u, int v, ll c) {
    ne[++tot] = h[u]; to[h[u] = tot] = v; co[tot] = c;
    ne[++tot] = h[v]; to[h[v] = tot] = u; co[tot] = 0;
}

bool bfs() {
    memset(d, 0, sizeof d); memcpy(now, h, sizeof h);
    queue<int> q; q.push(s); d[s] = 1;
    while (!q.empty()) {
        int x = q.front(); q.pop();
        for (int i = h[x]; i; i = ne[i]) if (co[i]) {
            int y = to[i];
            if (d[y]) continue;
            d[y] = d[x] + 1; q.push(y);
            if (y == t) return 1;
        }
    }
    return 0;
}

ll dinic(int x, ll flow) {
    if (x == t) return flow;
    ll rest = flow, k;
    for (int& i = now[x]; i && rest; i = ne[i]) if (co[i]) {
        int y = to[i];
        if (d[y] != d[x] + 1) continue;
        k = dinic(y, min(rest, co[i]));
        if (!k) { d[y] = 0; continue; }
        co[i] -= k, co[i ^ 1] += k; rest -= k;
    }
    return flow - rest;
}

bool check(ll mid) {
    memset(h, 0, sizeof h); memset(st, 0, sizeof st); tot = 1;
    rep (i, 1, n) {
        int cur = 0;
        rep (j, 1, k) if (dis[j][i] <= mid) cur ^= 1 << j - 1;
        st[cur] += a[i];
    }
    rep (i, 0, (1 << k) - 1) if (st[i]) {
        rep (j, 1, k) if (i >> j - 1 & 1) add(i, j + t, inf);
        add(s, i, st[i]);
    }
    rep (i, 1, k) add(i + t, t, sh[i].se);
    ll flow = 0, mx = 0;
    while (bfs()) while(flow = dinic(s, inf)) mx += flow;
    return mx == sum;
}

int main() {
    read(n, m, k); vector<ll> c;
    memset(dis, 0x3f, sizeof dis);
    rep (i, 1, n) read(a[i]), sum += a[i];
    rep (i, 1, m) {
        int u, v, c; read(u, v, c);
        e[u].pb({v, c}); e[v].pb({u, c});
    }
    rep (i, 1, k) {
        read(sh[i].fi, sh[i].se); dij(sh[i].fi, dis[i]);
        rep (j, 1, n) c.emplace_back(dis[i][j]);
    }
    sort(all(c));
    int l = 1, r = unique(all(c)) - c.begin(), ans;
    while (l <= r) {
        ll mid = l + r >> 1;
        if (check(c[mid - 1])) r = mid - 1, ans = mid;
        else l = mid + 1;
    }
    write(c[ans - 1]);
    return 0;
}

J - Janitor Troubles

多边形面积公式

int main() {
    IOS; double a, b, c, d; cin >> a >> b >> c >> d;
    double p = (a + b + c + d) / 2;
    cout << setprecision(7) << sqrt((p - a) * (p - b) * (p - c) * (p - d));
    return 0;
}

K - Kingpin Escape

不存在割边加点

int deg[N];
VI h[N], a;

void dfs(int x, int f) {
    if (deg[x] == 1) a.pb(x);
    for (auto y : h[x]) if (y != f) dfs(y, x);
}

int main(){
    IOS; cin >> n >> m; ++m;
    rep (i, 2, n) {
        int u, v; cin >> u >> v; ++v, ++u;
        h[u].pb(v); h[v].pb(u); ++deg[v]; ++deg[u];
    }
    dfs(m, 0);
    cout << (a.size() + 1 >> 1) << '
';
    rep (i, 1, a.size() >> 1) cout << a[i - 1] - 1 << ' ' << a[i + a.size() / 2 - 1] - 1 << '
';
    if (a.size() & 1) cout << a[a.size() >> 1] - 1 << ' ' << a.back() - 1;
    return 0;
}
原文地址:https://www.cnblogs.com/2aptx4869/p/14289920.html