제출 #424560

#제출 시각아이디문제언어결과실행 시간메모리
424560KoD저울 (IOI15_scales)C++17
100 / 100
709 ms8764 KiB
#include <bits/stdc++.h> #include "scales.h" template <int N, int... SZ> struct ArrayImpl { using type = std::array<typename ArrayImpl<SZ...>::type, N>; }; template <int N> struct ArrayImpl<N> { using type = std::array<int, N>; }; template <int... SZ> using Array = typename ArrayImpl<SZ...>::type; template <class T> using Vec = std::vector<T>; Array<720, 6> perm; Array<120, 4> query; Array<120, 720> rsp; // -2: done // -1: ng // other: next query std::map<Vec<int>, int> memo; int find_next(const Vec<int>& cand) { { const auto itr = memo.find(cand); if (itr != memo.end()) { return itr -> second; } } const int sz = (int) cand.size(); if (sz == 1) return memo[cand] = -2; int nsz = 1; while (nsz * 3 < sz) { nsz *= 3; } for (int i = 0; i < 120; ++i) { std::map<int, Vec<int>> next; for (const int p : cand) { next[rsp[i][p]].push_back(p); } bool ok = true; for (const auto& p: next) { if ((int) p.second.size() > nsz or find_next(p.second) == -1) { ok = false; break; } } if (ok) { return memo[cand] = i; } } return memo[cand] = -1; } void init(int) { { Array<6> ord; std::iota(ord.begin(), ord.end(), 1); for (int i = 0; i < 720; ++i) { perm[i] = ord; std::next_permutation(ord.begin(), ord.end()); } } { int idx = 0; for (int i = 0; i < 6; ++i) { for (int j = i + 1; j < 6; ++j) { for (int k = j + 1; k < 6; ++k) { for (int l = 0; l < 6; ++l) { query[idx++] = {i, j, k, l}; } } } } } for (int i = 0; i < 120; ++i) { auto ord = query[i]; for (int p = 0; p < 720; ++p) { std::sort(ord.begin(), ord.begin() + 3, [&](const int x, const int y) { return perm[p][x] < perm[p][y]; }); bool done = false; for (int k = 0; k < 3; ++k) { if (query[i][k] == query[i][3]) { rsp[i][p] = ord[k]; done = true; } } if (!done) { int idx = 0; while (perm[p][ord[idx]] < perm[p][ord[3]]) { idx += 1; } rsp[i][p] = (idx == 3 ? ord[0] : ord[idx]); } } } } void orderCoins() { Vec<int> cand(720); std::iota(cand.begin(), cand.end(), 0); while (cand.size() > 1) { const auto i = find_next(cand); const auto [a, b, c, d] = query[i]; Vec<int> next; const auto e = [&] { if (a == d) return getLightest(a + 1, b + 1, c + 1) - 1; if (b == d) return getMedian(a + 1, b + 1, c + 1) - 1; if (c == d) return getHeaviest(a + 1, b + 1, c + 1) - 1; return getNextLightest(a + 1, b + 1, c + 1, d + 1) - 1; }(); for (const auto p : cand) { if (rsp[i][p] == e) { next.push_back(p); } } cand = std::move(next); } const int p = cand[0]; int W[6]; std::iota(W, W + 6, 0); std::sort(W, W + 6, [&](const int x, const int y) { return perm[p][x] < perm[p][y]; }); for (auto& x : W) { x += 1; } answer(W); }
#Verdict Execution timeMemoryGrader output
Fetching results...