Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <algorithm>
- #include <set>
- #include <map>
- #include <cstring>
- #include <cstdio>
- #include <cassert>
- #include <queue>
- #include <bitset>
- #include <cmath>
- #include <sstream>
- #include <string>
- #include <vector>
- #define mp make_pair
- #define pb push_back
- #define sz(v) ((int)(v).size())
- #define all(v) (v).begin(),(v).end()
- using namespace std;
- typedef pair<int, int> ii;
- typedef long long int64;
- typedef vector<int> vi;
- template<class T> T abs(T x) {return x > 0 ? x : (-x); }
- template<class T> T sqr(T x) {return x * x; }
- typedef double D;
- const D eps = 1E-10;
- int sgn(D d) {
- if (abs(d) < eps) return 0;
- return d > 0 ? 1 : -1;
- }
- struct P {
- D x, y;
- P(){}
- P(D x, D y) : x(x), y(y) {}
- D len() {
- return sqrt(x * x + y * y);
- }
- P operator-(P p) {
- return P(x - p.x, y - p.y);
- }
- D operator*(P p) {
- return x * p.y - y * p.x;
- }
- D operator&(P p) {
- return x * p.x + y * p.y;
- }
- };
- bool cross(P p1, P p2, P q1, P q2) {
- return sgn((p1 - q1) * (q2 - q1)) * sgn((q2 - q1) * (p2 - q1)) > 0 &&
- sgn((q1 - p1) * (p2 - p1)) * sgn((p2 - p1) * (q2 - p1)) > 0;
- }
- D calc(vi &v, vector<P> &w) {
- D res = 0;
- for (int i = 0; i < sz(v); ++i) {
- int j = (i + 1) % sz(v);
- res += (w[v[i]] - w[v[j]]).len();
- }
- return res;
- }
- void reverse(vi& v, int s, int t) {
- while (1) {
- if (s == t) break;
- swap(v[s], v[t]);
- s = (s + 1) % sz(v);
- if (s == t) break;
- t = (t - 1 + sz(v)) % sz(v);
- if (s == t) break;
- }
- }
- vi S2opt(vi v, vector<P>& w) {
- while (1) {
- bool ch = false;
- for (int i = 0; i < sz(v); ++i) {
- for (int j = i + 2; j < sz(v); ++j) {
- int i0 = (i + 1) % sz(v);
- int j0 = (j + 1) % sz(v);
- if ((w[v[i]] - w[v[i0]]).len() + (w[v[j]] - w[v[j0]]).len() >
- (w[v[i]] - w[v[j]]).len() + (w[v[j0]] - w[v[i0]]).len() + eps) {
- ch = true;
- reverse(v, i0, j);
- }
- }
- }
- if (!ch) break;
- }
- return v;
- }
- /*
- vi S3opt(vi v, vector<P>& w) {
- while (1) {
- bool ch = false;
- }
- }
- */
- vi solve(vector<P> v, int ind) {
- int cur = ind;
- vi u(sz(v), 0);
- u[cur] = 1;
- vi res;
- res.pb(cur);
- int n = sz(v);
- for (int i = 0; i < n - 1; ++i) {
- int x = -1;
- D y = 1E100;
- vector<pair<D, int> > a;
- vector<pair<D, int> > aa;
- for (int j = 0; j < n; ++j)
- if (!u[j]) {
- /* bool ok = true;
- for (int k = 0; k + 1 < sz(res); ++k)
- if (cross(v[cur], v[j], v[res[k]], v[res[k + 1]])) {
- ok = false;
- break;
- }
- if (ok) */
- a.pb(mp((v[cur] - v[j]).len(), j));
- /* else
- aa.pb(mp((v[cur] - v[j]).len(), j));*/
- }
- if (!sz(a)) a = aa;
- sort(all(a));
- x = a[0].second;
- double cx = 1;
- for (int j = 0; j < sz(a); ++j) {
- if (cx < 100000) cx *= 3.0;
- int C = (int) cx + 1;
- if (rand() % C == 0) {
- x = a[j].second;
- break;
- }
- }
- res.pb(x);
- cur = x;
- u[cur] = true;
- }
- return res;
- }
- vi solve(vector<P> v) {
- vi res;
- D val = 1E100;
- for (int it = 0; it < 1000; ++it) {
- for (int i = 0; i < sz(v); ++i) {
- vi cur = solve(v, i);
- cur = S2opt(cur, v);
- if (calc(cur, v) < val) {
- val = calc(cur, v);
- res = cur;
- }
- }
- }
- /* for (int it = 0; it < 1000; ++it) {
- vi cur = res;
- for (int i = 0; i < 10; ++i) {
- int x = rand() % sz(v), y = rand() % sz(v);
- if (x != y) reverse(cur, x, y);
- }
- cur = S2opt(cur, v);
- if (calc(cur, v) < val) {
- val = calc(cur, v);
- res = cur;
- cerr << val << "\n";
- }
- }*/
- // res = 3opt(res);
- return res;
- }
- /*
- vector<P> V;
- vi sol;
- vi solve_brute(vector<P> v) {
- V = v;
- }
- */
- int main()
- {
- int n;
- cin >> n;
- vector<P> v(n);
- for (int i = 0; i < n; ++i)
- cin >> v[i].x >> v[i].y;
- vi res = solve(v);
- cout << calc(res, v) << "\n";
- for (int i = 0; i < sz(res); ++i)
- printf("%d ", res[i]);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement