#ifndef LOCAL #define FAST_IO #endif // ===== template.hpp ===== #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define OVERRIDE(a, b, c, d, ...) d #define REP2(i, n) for (i32 i = 0; i < (i32) (n); ++i) #define REP3(i, m, n) for (i32 i = (i32) (m); i < (i32) (n); ++i) #define REP(...) OVERRIDE(__VA_ARGS__, REP3, REP2)(__VA_ARGS__) #define PER(i, n) for (i32 i = (i32) (n) - 1; i >= 0; --i) #define ALL(x) begin(x), end(x) using namespace std; using u32 = unsigned int; using u64 = unsigned long long; using u128 = __uint128_t; using i32 = signed int; using i64 = signed long long; using i128 = __int128_t; using f64 = double; using f80 = long double; template using Vec = vector; template bool chmin(T &x, const T &y) { if (x > y) { x = y; return true; } return false; } template bool chmax(T &x, const T &y) { if (x < y) { x = y; return true; } return false; } istream &operator>>(istream &is, i128 &x) { i64 v; is >> v; x = v; return is; } ostream &operator<<(ostream &os, i128 x) { os << (i64) x; return os; } istream &operator>>(istream &is, u128 &x) { u64 v; is >> v; x = v; return is; } ostream &operator<<(ostream &os, u128 x) { os << (u64) x; return os; } [[maybe_unused]] constexpr i32 INF = 1000000100; [[maybe_unused]] constexpr i64 INF64 = 3000000000000000100; struct SetUpIO { SetUpIO() { #ifdef FAST_IO ios::sync_with_stdio(false); cin.tie(nullptr); #endif cout << fixed << setprecision(15); } } set_up_io; // ===== template.hpp ===== #ifdef DEBUGF #include "cpl/template/debug.hpp" #else #define DBG(x) (void) 0 #endif // ===== timer.hpp ===== #include class Timer { std::chrono::high_resolution_clock::time_point st; public: Timer() : st(std::chrono::high_resolution_clock::now()) {} void reset() { st = std::chrono::high_resolution_clock::now(); } int elapsed() { auto ed = std::chrono::high_resolution_clock::now(); return (int) std::chrono::duration_cast(ed - st).count(); } }; // ===== timer.hpp ===== // ===== xorshift.hpp ===== class XorShift64 { unsigned long long x; public: XorShift64(unsigned long long seed) : x((seed + 14213124131ull) ^ 103920984124ull) {} unsigned long long operator()() { x = x ^ (x << 13); x = x ^ (x >> 7); x = x ^ (x << 17); return x; } template T uniform(T mn, T mx) { return mn + (T) ((*this)() % (mx - mn + 1)); } double as_f64() { return (double) (*this)() / ~0ull; } }; // ===== xorshift.hpp ===== constexpr i32 N = 100; constexpr i32 M = 8; constexpr i32 POS_MIN = 0; constexpr i32 POS_MAX = 1000; [[maybe_unused]] constexpr i32 V_MIN = 1; [[maybe_unused]] constexpr i32 V_MAX = 100000; int dist_two(int x, int y, int p, int q) { return (x - p) * (x - p) + (y - q) * (y - q); } struct Input { i32 n, m; Vec a, b; }; struct Output { Vec c, d; i32 v; Vec t, r; }; Input read_input() { auto &fin = cin; i32 n, m; fin >> n >> m; assert(n == N); assert(m == M); Vec a(n), b(n); REP(i, n) { fin >> a[i] >> b[i]; assert(POS_MIN <= a[i] && a[i] <= POS_MAX); assert(POS_MIN <= b[i] && b[i] <= POS_MAX); } return Input{n, m, a, b}; } i32 calc_energey(const Input &input, const Output &output, i32 i, i32 j) { i32 x, y, p, q; if (output.t[i] == 0) { x = input.a[output.r[i]]; y = input.b[output.r[i]]; } else { x = output.c[output.r[i]]; y = output.d[output.r[i]]; } if (output.t[j] == 0) { p = input.a[output.r[j]]; q = input.b[output.r[j]]; } else { p = output.c[output.r[j]]; q = output.d[output.r[j]]; } i32 dist = dist_two(p, q, x, y); if (output.t[i] == 0 && output.t[j] == 0) { return 25 * dist; } else if (output.t[i] == 1 && output.t[j] == 1) { return dist; } else { return 5 * dist; } } i64 calc_energey_sum(const Input &input, const Output &output) { i64 s = 0; REP(i, output.v - 1) { s += calc_energey(input, output, i, i + 1); } return s; } Output solve(Input input) { constexpr i32 TL = 900; Timer timer; XorShift64 rd(998244353); Output output; output.c.resize(input.m, 0); output.d.resize(input.m, 0); output.v = 0; REP(i, input.m) { //output.c[i] = rd.uniform(POS_MIN, POS_MAX); //output.d[i] = rd.uniform(POS_MIN, POS_MAX); i32 center = rd.uniform(0, input.n - 1); i32 dx = rd.uniform(-100, 100); i32 dy = rd.uniform(-100, 100); output.c[i] = clamp(input.a[center] + dx, POS_MIN, POS_MAX); output.d[i] = clamp(input.b[center] + dy, POS_MIN, POS_MAX); } output.v = input.n + 1; output.t.resize(input.n + 1, 0); output.r.resize(input.n + 1, 0); iota(output.r.begin(), output.r.begin() + input.n, 0); auto uniform_range = [&rd](i32 n) -> pair { i32 l = rd.uniform(0, n); i32 r = rd.uniform(0, n); while (l == r) { l = rd.uniform(0, n); r = rd.uniform(0, n); } if (l > r) { swap(l, r); } return pair(l, r); }; auto try_reverse = [&](double temp) -> void { auto [l, r] = uniform_range(output.v - 2); ++l; ++r; i32 diff = 0; diff -= calc_energey(input, output, l - 1, l); diff -= calc_energey(input, output, r - 1, r); diff += calc_energey(input, output, l - 1, r - 1); diff += calc_energey(input, output, l, r); if (diff <= 0 || rd.as_f64() < exp(-diff / temp)) { reverse(output.t.begin() + l, output.t.begin() + r); reverse(output.r.begin() + l, output.r.begin() + r); } }; auto try_insert = [&](double temp) -> void { i32 stt = rd.uniform(0, input.m - 1); i32 pos = rd.uniform(0, output.v - 2); i32 diff = 0; diff -= calc_energey(input, output, pos, pos + 1); if (output.t[pos] == 0) { diff += 5 * dist_two(input.a[output.r[pos]], input.b[output.r[pos]], output.c[stt], output.d[stt]); } else { diff += dist_two(output.c[output.r[pos]], output.d[output.r[pos]], output.c[stt], output.d[stt]); } if (output.t[pos + 1] == 0) { diff += 5 * dist_two(input.a[output.r[pos + 1]], input.b[output.r[pos + 1]], output.c[stt], output.d[stt]); } else { diff += dist_two(output.c[output.r[pos + 1]], output.d[output.r[pos + 1]], output.c[stt], output.d[stt]); } if (diff < 0) { output.v += 1; output.t.insert(output.t.begin() + pos + 1, 1); output.r.insert(output.r.begin() + pos + 1, stt); } }; auto try_remove = [&](double temp) -> void { Vec stt_pos; REP(i, output.v) { if (output.t[i] == 1) { stt_pos.push_back(i); } } if (stt_pos.empty()) { return; } i32 pos = stt_pos[rd.uniform(0, (i32) stt_pos.size() - 1)]; i32 stt = output.r[pos]; i32 diff = 0; diff += calc_energey(input, output, pos - 1, pos + 1); if (output.t[pos] == 0) { diff -= 5 * dist_two(input.a[output.r[pos]], input.b[output.r[pos]], output.c[stt], output.d[stt]); } else { diff -= dist_two(output.c[output.r[pos]], output.d[output.r[pos]], output.c[stt], output.d[stt]); } if (output.t[pos + 1] == 0) { diff -= 5 * dist_two(input.a[output.r[pos + 1]], input.b[output.r[pos + 1]], output.c[stt], output.d[stt]); } else { diff -= dist_two(output.c[output.r[pos + 1]], output.d[output.r[pos + 1]], output.c[stt], output.d[stt]); } if (diff < 0) { output.v -= 1; output.t.erase(output.t.begin() + pos); output.r.erase(output.r.begin() + pos); } }; constexpr double BEGIN_TEMP = 100; constexpr double END_TEMP = 0.1; double temp = BEGIN_TEMP; i32 iter = 0; while (true) { if (iter % 64 == 0) { double t = 1.0 * timer.elapsed() / TL; if (t > 1) { break; } temp = (1 - t) * BEGIN_TEMP + t * END_TEMP; } i32 type = rd.uniform(0, 9); if (type >= 0 && type <= 7) { try_reverse(temp); } else if (type == 8) { try_insert(temp); } else { try_remove(temp); } ++iter; } return output; } int main() { Input input = read_input(); Output output = solve(input); REP(i, input.m) { cout << output.c[i] << ' ' << output.d[i] << '\n'; } cout << output.v << '\n'; REP(i, output.v) { cout << output.t[i] + 1 << ' ' << output.r[i] + 1 << '\n'; } //cerr << "score: " << 1e9 / (1000.0 + sqrt(calc_energey_sum(input, output))) << '\n'; }