Submission #1256232

#TimeUsernameProblemLanguageResultExecution timeMemory
1256232biankScales (IOI15_scales)C++20
Compilation error
0 ms0 KiB
#include <bits/stdc++.h>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); i++)
#define forsn(i, s, n) for (int i = int(s); i < int(n); i++)
#define dforn(i, n) for (int i = int(n) - 1; i >= 0; i--)
#define dforsn(i, s, n) for (int i = int(n) - 1; i >= int(s); i--)

using vi = vector<int>;
using ll = long long;
using ii = pair<int, int>;

#define fst first
#define snd second

#define all(x) begin(x), end(x)
#define sz(x) int(x.size())

#define pb push_back
#define eb emplace_back

const int N = 6;
const int M = 720;

vi orders[M];

int simulate(int A, int B, int C, int D, int t, int orderIdx) {
    const vi &order = orders[orderIdx];
    vi v = {A, B, C};
    sort(all(v), [&](const int &lhs, const int &rhs) {
        return order[lhs] < order[rhs];
    });
    tie(A, B, C) = make_tuple(v[0], v[1], v[2]);
    if (t == 0) return B;
    if (t == 1) return A;
    if (t == 2) return C;
    assert(t == 3 && D != -1);
    if (order[A] > order[D]) return A;
    if (order[B] > order[D]) return B;
    if (order[C] > order[D]) return C;
    return A;
}

int doQuery(int A, int B, int C, int D, int t) {
    A++, B++, C++, D++;
    if (t == 0) return getMedian(A, B, C) - 1;
    if (t == 1) return getLightest(A, B, C) - 1;
    if (t == 2) return getHeaviest(A, B, C) - 1;
    return getNextLightest(A, B, C, D) - 1;
}

int pot[N + 1];

map<pair<vi, int>, bool> memo;

vector<tuple<int, int, int, int, int>> all_moves;

vector<vi> division(int A, int B, int C, int D, int t, vi &possibilities) {
    vector<vi> ret(3);
    for (auto p : possibilities) {
        int r = simulate(A, B, C, D, t, p);
        int id = r == C ? 2 : r == B;
        ret[id].pb(p);
    }
    return ret;
}

bool solve(vi &possibilities, int moves) {
    pair<vi, int> state = {possibilities, moves};
    if (memo.count(state)) return memo[state];
    if (sz(possibilities) <= 1) {
        return memo[state] = true;
    }
    if (sz(possibilities) > pot[6 - moves]) return false;
    vector<pair<vector<vi>, int>> options;
    int idx = 0;
    for (auto [A, B, C, D, t] : all_moves) {
        vector<vi> groups = division(A, B, C, D, t, possibilities);
        if (sz(groups[0]) == sz(possibilities) ||
            sz(groups[1]) == sz(possibilities) ||
            sz(groups[2]) == sz(possibilities)) {
            continue;
        }
        options.eb(groups, idx);
        idx++;
    }
    sort(all(options), [&](const auto &A, const auto &B) {
        auto &lhs = A.fst, &rhs = B.fst;
        return max({sz(lhs[0]), sz(lhs[1]), sz(lhs[2])}) < max({sz(rhs[0]), sz(rhs[1]), sz(rhs[2])});
    });
    for (auto [groups, i] : options) {
        if (solve(groups[0], moves + 1) &&
            solve(groups[1], moves + 1) &&
            solve(groups[2], moves + 1)) {
            return memo[state] = true;
        }
    }
    return memo[state] = false;
}

int first_move = 75;
int second_move = 18;

void init(int /*T*/) {
    pot[0] = 1;
    forn(i, N) pot[i + 1] = pot[i] * 3;
    vi order(N);
    iota(all(order), 0);
    int i = 0;
    do orders[i++] = order;
    while (next_permutation(all(order)));
    forn(A, N) forn(B, A) forn(C, B) forn(t, 3) all_moves.eb(A, B, C, -1, t);
    forn(D, N) forn(A, N) forn(B, A) forn(C, B) {
        if (A != D && B != D && C != D) {
            all_moves.eb(A, B, C, D, 3);
        }
    }
    vi possibilities(M);
    iota(all(possibilities), 0);
    auto [A, B, C, D, t] = all_moves[first_move];
    vector<vi> groups = division(A, B, C, D, t, possibilities);
    forn(i, 3) {
        tie(A, B, C, D, t) = all_moves[second_move];
        vector<vi> other_groups = division(A, B, C, D, t, groups[i]);
        forn(j, 3) solve(other_groups[j], 2);
    }
}

void doMove(vi &possibilities, int moves) {
    int idx = 0;
    for (auto [A, B, C, D, t] : all_moves) {
        vector<vi> groups = division(A, B, C, D, t, possibilities);
        if (sz(groups[0]) == sz(possibilities) ||
            sz(groups[1]) == sz(possibilities) ||
            sz(groups[2]) == sz(possibilities)) {
            continue;
        }
        if (memo[{groups[0], moves + 1}] &&
            memo[{groups[1], moves + 1}] &&
            memo[{groups[2], moves + 1}]) {
            int r = doQuery(A, B, C, D, t);
            int id = r == C ? 2 : r == B;
            possibilities = groups[id];
            return;
        }
        idx++;
    }
    assert(false);
}

void orderCoins() {
    vi possibilities(M);
    iota(all(possibilities), 0);
    for (auto i : {first_move, second_move}) {
        auto [A, B, C, D, t] = all_moves[i];
        vector<vi> groups = division(A, B, C, D, t, possibilities);
        int r = doQuery(A, B, C, D, t);
        int id = r == C ? 2 : r == B;
        possibilities = groups[id];
    }
    int moves = 2;
    while (sz(possibilities) > 1) {
        pair<vi, int> state = {possibilities, moves};
        assert(memo[state]);
        doMove(possibilities, moves);
        moves++;
    }
    assert(sz(possibilities) == 1);
    assert(moves <= 6);
    vi ans = orders[possibilities.back()];
    int ret[N];
    forn(i, N) ret[ans[i]] = i + 1;
    answer(ret);
}

Compilation message (stderr)

scales.cpp: In function 'int doQuery(int, int, int, int, int)':
scales.cpp:47:24: error: 'getMedian' was not declared in this scope
   47 |     if (t == 0) return getMedian(A, B, C) - 1;
      |                        ^~~~~~~~~
scales.cpp:48:24: error: 'getLightest' was not declared in this scope
   48 |     if (t == 1) return getLightest(A, B, C) - 1;
      |                        ^~~~~~~~~~~
scales.cpp:49:24: error: 'getHeaviest' was not declared in this scope
   49 |     if (t == 2) return getHeaviest(A, B, C) - 1;
      |                        ^~~~~~~~~~~
scales.cpp:50:12: error: 'getNextLightest' was not declared in this scope
   50 |     return getNextLightest(A, B, C, D) - 1;
      |            ^~~~~~~~~~~~~~~
scales.cpp: In function 'void orderCoins()':
scales.cpp:174:5: error: 'answer' was not declared in this scope
  174 |     answer(ret);
      |     ^~~~~~