結果
問題 | No.5007 Steiner Space Travel |
ユーザー | t33f |
提出日時 | 2022-07-30 15:50:18 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 982 ms / 1,000 ms |
コード長 | 6,104 bytes |
コンパイル時間 | 1,575 ms |
実行使用メモリ | 3,824 KB |
スコア | 8,380,451 |
最終ジャッジ日時 | 2022-07-30 15:50:52 |
合計ジャッジ時間 | 33,470 ms |
ジャッジサーバーID (参考情報) |
judge10 / judge11 |
純コード判定しない問題か言語 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 982 ms
3,668 KB |
testcase_01 | AC | 981 ms
3,728 KB |
testcase_02 | AC | 982 ms
3,588 KB |
testcase_03 | AC | 982 ms
3,736 KB |
testcase_04 | AC | 982 ms
3,704 KB |
testcase_05 | AC | 981 ms
3,580 KB |
testcase_06 | AC | 982 ms
3,628 KB |
testcase_07 | AC | 980 ms
3,588 KB |
testcase_08 | AC | 981 ms
3,708 KB |
testcase_09 | AC | 982 ms
3,820 KB |
testcase_10 | AC | 982 ms
3,732 KB |
testcase_11 | AC | 982 ms
3,652 KB |
testcase_12 | AC | 982 ms
3,588 KB |
testcase_13 | AC | 982 ms
3,736 KB |
testcase_14 | AC | 982 ms
3,680 KB |
testcase_15 | AC | 982 ms
3,700 KB |
testcase_16 | AC | 982 ms
3,712 KB |
testcase_17 | AC | 981 ms
3,684 KB |
testcase_18 | AC | 981 ms
3,736 KB |
testcase_19 | AC | 981 ms
3,656 KB |
testcase_20 | AC | 981 ms
3,740 KB |
testcase_21 | AC | 981 ms
3,684 KB |
testcase_22 | AC | 981 ms
3,588 KB |
testcase_23 | AC | 982 ms
3,584 KB |
testcase_24 | AC | 981 ms
3,592 KB |
testcase_25 | AC | 982 ms
3,740 KB |
testcase_26 | AC | 981 ms
3,584 KB |
testcase_27 | AC | 982 ms
3,584 KB |
testcase_28 | AC | 982 ms
3,824 KB |
testcase_29 | AC | 982 ms
3,656 KB |
ソースコード
#include <cmath> #include <map> #include <array> #include <algorithm> #include <chrono> #include <random> #include <vector> #include <numeric> #include <cassert> #include <iostream> using namespace std; class Timer { chrono::system_clock::time_point start_time = chrono::system_clock::now(); public: Timer() {} long long get_elapsed_time() { auto diff = chrono::system_clock::now() - start_time; return chrono::duration_cast<chrono::milliseconds>(diff).count(); } } timer; using P = pair<int, int>; constexpr int N = 100, M = 8; int a[N], b[N]; void read_input() { { int n, m; cin >> n >> m; assert(n == N); assert(m == M); } for (int i = 0; i < N; i++) cin >> a[i] >> b[i]; } mt19937 mt; constexpr int alpha = 5; int L22(int x1, int y1, int x2, int y2) { const int dx = x1 - x2, dy = y1 - y2; return dx * dx + dy * dy; } int L22(P p, P q) { return L22(p.first, p.second, q.first, q.second); } int cost(int i, int j) { return L22(a[i], b[i], a[j], b[j]) * alpha * alpha; } int cost(int i, int j, P middle) { return (L22(a[i], b[i], middle.first, middle.second) + L22(a[j], b[j], middle.first, middle.second)) * alpha; } int cost(int t1, P p1, int t2, P p2) { const int coeff = (t1 == 1 && t2 == 1 ? alpha * alpha : t1 == 1 || t2 == 1 ? alpha : 1); return coeff * L22(p1, p2); } vector<int> solve_tsp(int tl) { vector<int> ans(N); iota(ans.begin(), ans.end(), 0); int total_cost = 0; for (int i = 0; i < N; i++) { if (i + 1 < N) total_cost += cost(i, i + 1); else total_cost += cost(0, N - 1); } Timer timer; uniform_int_distribution<int> randindex(0, N - 1); int iter = 0, last_upd = 0, stop_threshold = N * N; while (timer.get_elapsed_time() < tl && last_upd + stop_threshold > iter) { int i = randindex(mt), j = randindex(mt); assert(i < N); assert(j < N); if (i == j) continue; if (i > j) swap(i, j); if (i + 1 == j) continue; iter++; const int k = (j + 1 == N ? 0 : j + 1); const int diff = (cost(ans[i], ans[j]) + cost(ans[i + 1], ans[k]) - cost(ans[i], ans[i + 1]) - cost(ans[j], ans[k])); if (diff <= 0) { reverse(ans.begin() + i + 1, ans.begin() + j + 1); total_cost += diff; last_upd = iter; // cerr << iter << ' ' << total_cost << endl; } } cerr << iter << ' ' << total_cost << endl; return ans; } class DSU { vector<int> par, rank; public: explicit DSU(int n) : par(n), rank(n, 0) { iota(par.begin(), par.end(), 0); } int find(int i) { return (par[i] == i) ? i : (par[i] = find(par[i])); } void merge(int i, int j) { int x = find(i), y = find(j); if (x != y) { if (rank[x] < rank[y]) par[x] = y; else { par[y] = x; if (rank[x] == rank[y]) rank[x]++; } } } bool same(int i, int j) { return find(i) == find(j); } }; struct Target { int type, idx; Target(int type, int idx) : type(type), idx(idx) { assert(type == 1 || type == 2); } }; struct Config { vector<int> path; array<P, M> stations; }; pair<vector<Target>, long long> greedy(const Config &conf) { vector<Target> ans; ans.emplace_back(1, conf.path[0]); for (int i = 0; i < N; i++) { int cur_cost = cost(conf.path[i], conf.path[i + 1]), t = -1, s = -1; for (int j = 0; j < M; j++) { const int tmp = cost(conf.path[i], conf.path[i + 1], conf.stations[j]); if (tmp < cur_cost) { cur_cost = tmp; t = 2; s = j; } } const int l = conf.path[i], r = conf.path[i + 1]; const P p1 = {a[l], b[l]}, p2 = {a[r], b[r]}; for (int j = 0; j < N; j++) { const P p = {a[j], b[j]}; const int tmp = cost(1, p1, 1, p) + cost(1, p, 1, p2); if (tmp < cur_cost) { cur_cost = tmp; t = 1; s = j; } } if (s >= 0) { ans.emplace_back(t, s); } ans.emplace_back(1, conf.path[i + 1]); } long long total_cost = 0; for (size_t i = 0; i + 1 < ans.size(); i++) { const auto [t1, i1] = ans[i]; const auto [t2, i2] = ans[i + 1]; const P p1 = (t1 == 1 ? make_pair(a[i1], b[i1]) : conf.stations[i1]), p2 = (t2 == 1 ? make_pair(a[i2], b[i2]) : conf.stations[i2]); total_cost += cost(t1, p1, t2, p2); } return {ans, total_cost}; } int main() { read_input(); vector<int> path = solve_tsp(200); { auto start = find(path.begin(), path.end(), 0); assert(start != path.end()); rotate(path.begin(), start, path.end()); assert(path.front() == 0); path.push_back(0); } array<P, M> stations{ P{200, 333}, {200, 667}, {400, 333}, {400, 667}, {600, 333}, {600, 667}, {800, 333}, {800, 667}, }; auto [ans, cur_cost] = greedy({path, stations}); int iter = 0; uniform_int_distribution<int> rand_pos(10, 990); while (timer.get_elapsed_time() < 980) { iter++; const int i = iter % M; const P origp = stations[i], newp = P(rand_pos(mt), rand_pos(mt)); stations[i] = newp; const auto [tmp_ans, tmp_cost] = greedy({path, stations}); if (tmp_cost < cur_cost) { cur_cost = tmp_cost; ans = tmp_ans; cerr << iter << ' ' << cur_cost << ' ' << round(1e9 / (1000 + sqrt(cur_cost))) << endl; } else { // rollback stations[i] = origp; } } // output for (auto [x, y] : stations) cout << x << ' ' << y << '\n'; cout << ans.size() << '\n'; for (auto [t, i] : ans) cout << t << ' ' << i + 1 << '\n'; }