結果
問題 | No.5007 Steiner Space Travel |
ユーザー | hotpepsi |
提出日時 | 2023-04-29 13:40:46 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 972 ms / 1,000 ms |
コード長 | 5,206 bytes |
コンパイル時間 | 1,686 ms |
コンパイル使用メモリ | 116,980 KB |
実行使用メモリ | 4,376 KB |
スコア | 7,828,102 |
最終ジャッジ日時 | 2023-04-29 13:41:21 |
合計ジャッジ時間 | 33,870 ms |
ジャッジサーバーID (参考情報) |
judge12 / judge14 |
純コード判定しない問題か言語 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 963 ms
4,368 KB |
testcase_01 | AC | 953 ms
4,372 KB |
testcase_02 | AC | 941 ms
4,372 KB |
testcase_03 | AC | 968 ms
4,368 KB |
testcase_04 | AC | 952 ms
4,368 KB |
testcase_05 | AC | 960 ms
4,368 KB |
testcase_06 | AC | 962 ms
4,372 KB |
testcase_07 | AC | 966 ms
4,368 KB |
testcase_08 | AC | 964 ms
4,372 KB |
testcase_09 | AC | 939 ms
4,368 KB |
testcase_10 | AC | 960 ms
4,372 KB |
testcase_11 | AC | 959 ms
4,368 KB |
testcase_12 | AC | 971 ms
4,372 KB |
testcase_13 | AC | 946 ms
4,368 KB |
testcase_14 | AC | 942 ms
4,372 KB |
testcase_15 | AC | 962 ms
4,368 KB |
testcase_16 | AC | 951 ms
4,368 KB |
testcase_17 | AC | 963 ms
4,372 KB |
testcase_18 | AC | 961 ms
4,372 KB |
testcase_19 | AC | 933 ms
4,368 KB |
testcase_20 | AC | 958 ms
4,376 KB |
testcase_21 | AC | 944 ms
4,368 KB |
testcase_22 | AC | 954 ms
4,372 KB |
testcase_23 | AC | 972 ms
4,372 KB |
testcase_24 | AC | 930 ms
4,372 KB |
testcase_25 | AC | 963 ms
4,368 KB |
testcase_26 | AC | 938 ms
4,368 KB |
testcase_27 | AC | 971 ms
4,372 KB |
testcase_28 | AC | 958 ms
4,372 KB |
testcase_29 | AC | 945 ms
4,372 KB |
ソースコード
#include <iostream> #include <sstream> #include <cassert> #include <cmath> #include <cstring> #include <chrono> #include <algorithm> #include <numeric> #include <vector> #include <queue> #include <string> #include <set> #include <map> #include <unordered_map> #include <random> using namespace std; #if defined(_MSC_VER) || defined(__APPLE_CC__) #define LOCAL #endif const int TIME_LIMIT = 6000 - 100; const int INF = 1000000000; typedef pair<int, int> II; std::random_device seed_gen; std::mt19937_64 engine(seed_gen()); auto start_time = chrono::high_resolution_clock::now(); inline int get_elapsed_ms() { return int(chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count()); } struct Solver { int N; int M; vector<int> y, x, g; void input() { cin >> N >> M; y.resize(N + M); x.resize(N + M); g.resize(N + M); for (int i = 0; i < N; ++i) { cin >> y[i] >> x[i]; } } void prepare() { } int64_t get_dist(int a, int b) { int dx = x[b] - x[a], dy = y[b] - y[a]; int64_t dist = dx * dx + dy * dy; if (a < N) dist *= 5; if (b < N) dist *= 5; return dist; } void output(const vector<int>& ans) { for (int i = 0; i < M; ++i) { cout << y[i + N] << " " << x[i + N] << endl; } cout << ans.size() << endl; for (int x : ans) { if (x < N) { cout << "1 " << (x + 1) << endl; } else { cout << "2 " << (x - N + 1) << endl; } } } bool classify() { for (int i = 0; i < N; ++i) { g[i] = engine() % M; } bool done = false; while (!done) { done = true; vector<int> xx(M), yy(M), cnt(M); for (int i = 0; i < N; ++i) { xx[g[i]] += x[i]; yy[g[i]] += y[i]; cnt[g[i]] += 1; } for (int i = 0; i < M; ++i) { if (cnt[i]) { xx[i] /= cnt[i]; yy[i] /= cnt[i]; x[N + i] = xx[i]; y[N + i] = yy[i]; } } for (int i = 0; i < N; ++i) { int md = INF, next_g = -1; for (int j = 0; j < M; ++j) { int dx = x[i] - xx[j], dy = y[i] - yy[j], d = dx * dx + dy * dy; if (d < md) { md = d; next_g = j; } } if (g[i] != next_g) { done = false; g[i] = next_g; } } } vector<int> cnt(M); for (int i = 0; i < N; ++i) { cnt[g[i]] += 1; } for (int i = 0; i < M; ++i) { if (cnt[i] == 0) { return false; } } return true; } vector<int> gen(int prev_point, int group, const vector<int>& points) { vector<int> r; if (points.size() > 60) { return r; } vector<int> closest_points(points.size()); for (int i = 0; i < points.size(); ++i) { int64_t min_dist = 1LL << 60; int& closest = closest_points[i]; for (int j = 0; j < points.size(); ++j) { if (i == j) continue; int64_t dist = get_dist(points[i], points[j]); if (dist < min_dist) { min_dist = dist; closest = j; } } } int64_t min_cost = 1LL << 60; for (int i = 0; i < 15; ++i) { int64_t cost = 0, vis = 0, all = (1LL << points.size()) - 1; vector<int> path; int p = prev_point, pi = -1; if (!points.empty() && points.front() == prev_point) { pi = 0; vis |= 1; } while (vis != all) { int next_index = -1, next = N + group; if (engine() % 2) { if (pi >= 0) { int next_candidate = closest_points[pi]; if ((vis & (1LL << next_candidate)) == 0) { next_index = next_candidate; next = points[next_index]; } } } while (p == next) { int next_candidate = engine() % points.size(); if ((vis & (1LL << next_candidate)) == 0) { next_index = next_candidate; next = points[next_index]; } } cost += get_dist(p, next); path.emplace_back(next); if (next_index >= 0) { vis |= (1LL << next_index); } pi = next_index; p = next; } cost += get_dist(path.empty() ? prev_point : path.back(), N + group); path.emplace_back(N + group); if (cost < min_cost) { min_cost = cost; r = path; } } return r; } vector<int> gen(const vector<int> &seq) { vector<int> r; r.emplace_back(0); for (int gg = 0; gg < M; ++gg) { vector<int> points; int target_group = seq[gg]; for (int i = 0; i < N; ++i) { if (g[i] == target_group) { points.emplace_back(i); } } for (auto x : gen(r.back(), target_group, points)) { r.emplace_back(x); } } for (auto x : gen(r.back(), seq[0], {})) { r.emplace_back(x); } r.emplace_back(0); return r; } int64_t evaluate(const vector<int>& r) { int64_t s = 0; int prev = 0; for (int next : r) { s += get_dist(prev, next); prev = next; } return s; } void run() { int64_t min_score = 1LL << 60; vector<int> ans; while (!classify()) { ; } vector<int> seq(M+1); iota(seq.begin(), seq.end(), 0); seq[M] = g[0]; do { if (seq[0] == g[0]) { vector<int> r = gen(seq); int64_t score = evaluate(r); if (score < min_score) { min_score = score; ans = r; } } } while (next_permutation(seq.begin(), seq.begin() + M)); output(ans); } }; int main(int argc, char* argv[]) { #if DEBUG freopen("in.txt", "r", stdin); #endif Solver solver; solver.input(); solver.prepare(); solver.run(); }