QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#65569#3858. Systematic salesmanUBB_Zalau00#ML 0ms0kbC++144.8kb2022-12-01 20:51:272022-12-01 20:51:28

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2022-12-01 20:51:28]
  • 评测
  • 测评结果:ML
  • 用时:0ms
  • 内存:0kb
  • [2022-12-01 20:51:27]
  • 提交

answer

#include <bits/stdc++.h>
#ifdef LOCAL_DEFINE
#include <dbg.h>
#else
#define dbg(...)
#endif

using namespace std;

struct Point {
  int x, y;
  int id;
  double Dist(const Point &other) const {
    return sqrt(1LL * (x - other.x) * (x - other.x) + 1LL * (y - other.y) * (y - other.y));
  }
};

bool CompByX(const Point &a, const Point &b) {
  return a.x < b.x;
}

bool CompByY(const Point &a, const Point &b) {
  return a.y < b.y;
}

typedef bool (*Comp)(const Point &a, const Point &b);

Comp GetComp(int type) {
  return type == 0 ? CompByX : CompByY;
}


const int N = 1001;

double dp[N][N];
double dp2[N][N];
double dist[N][N];
int recon[N][N];
int recon2[N][N];
Point pts[N];

int Mid(int l, int r) {
  return (l + r + 1) / 2;
}

void Sort(int l, int r, int type) {
  if (l == r) return;
  sort(pts + l, pts + r + 1, GetComp(type));
  int m = Mid(l, r);
  Sort(l, m - 1, 1 ^ type);
  Sort(m, r, 1 ^ type);
}

template<typename T>
bool Min(T &a, const T &b) { return a < b ? false : (a = b, true); }

bool known[N][N];
vector<int> ans[N][N];

void Divide(int l, int r) {
  if (l == r) {
    dp[l][r] = 0;
    return;
  }
  int m = Mid(l, r);
  Divide(l, m - 1);
  Divide(m, r);

  if (l + 1 == r) {
    dp[l][r] = dp[r][l] = dist[l][r]; 
    known[l][r] = known[r][l] = true;
    ans[l][r] = {l, r};
    ans[r][l] = {r, l};
    return;
  }

  if (l + 2 == r) {
    dp[l][r] = dist[l][l + 1] + dp[l + 1][r];
    dp[l][l + 1] = dist[l][r] + dp[r][l + 1];
    dp[r][l] = dp[l][r];
    dp[l + 1][l] = dp[l][l + 1];
    known[l][r] = known[r][l] = true;
    known[l][l + 1] = known[l + 1][l] = true;
    ans[l][r] = {l, l + 1, r};
    ans[l][l + 1] = {l, r, l + 1};
    ans[r][l] = {r, l + 1, l};
    ans[l + 1][l] = {l + 1, r, l};
    return;
  }

  int lim = Mid(l, m - 1);
  for (int u = l; u < m; ++u) {
    for (int j = m; j <= r; ++j) {
      if (u < lim)
        for (int i = lim; i <= m - 1; ++i) {
          if (Min(dp2[u][j], dp[u][i] + dist[i][j])) {
            recon2[u][j] = i;
          }
        }
      else
        for (int i = l; i < lim; ++i) {
          if (Min(dp2[u][j], dp[u][i] + dist[i][j])) {
            recon2[u][j] = i;
          }
        }
    }
  }
  
  lim = Mid(m, r);
  for (int u = l; u < m; ++u) {
    for (int v = m; v <= r; ++v) {
      if (v < lim)
        for (int j = lim; j <= r; ++j) {
          if (Min(dp[u][v], dp2[u][j] + dp[j][v])) {
            recon[u][v] = j;
          }
        }
      else
        for (int j = m; j < lim; ++j) {
          if (Min(dp[u][v], dp2[u][j] + dp[j][v])) {
            recon[u][v] = j;
          }
        }
      dp[v][u] = dp[u][v];
      recon[v][u] = recon[u][v];
    }
  }
}

const double EPS = 1e-6;

bool Eq(double a, double b) {
  return fabs(a - b) <= EPS;
}

void Reconstr(int l, int r) {
  dbg("Recon", l, r);
  if (l == r) {
    cout << pts[l].id << ' ';
    return;
  }
  if (known[l][r]) {
    for (int x : ans[l][r]) cout << pts[x].id << ' ';
    return;
    if (l + 1 == r) {
      cout << pts[l].id << ' ' << pts[r].id << ' ';
      return;
    }
    if (r + 1 == l) {
      cout << pts[r].id << ' ' << pts[l].id << ' ';
      return;
    }
    if (l + 2 == r) {
      if (Eq(dist[l][l + 1] + dist[l + 1][r], dp[l][r])) {
        cout << pts[l].id << ' ' << pts[l + 1].id << ' ' << pts[r].id << ' ';
      } else {
        cout << pts[l].id << ' ' << pts[r].id << ' ' << pts[l + 1].id << ' ';
      }
      return;
    }
    if (r + 2 == l) {
      if (Eq(dist[r][r + 1] + dist[r + 1][l], dp[r][l])) {
        cout << pts[r].id << ' ' << pts[r + 1].id << ' ' << pts[l].id << ' ';
      } else {
        cout << pts[r].id << ' ' << pts[l].id << ' ' << pts[r + 1].id << ' ';
      }
      return;
    }
  }
  int r2 = recon[l][r];
  int r1 = recon2[l][r2];
  Reconstr(l, r1);
  Reconstr(r2, r);
}


int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);

  int n; cin >> n;
  for (int i = 0; i < n; ++i) {
    cin >> pts[i].x >> pts[i].y;
    pts[i].id = i + 1;
  }
  if (n == 1) {
    cout << 0 << endl;
    return 0;
  }
  Sort(0, n - 1, 0);
  for (int i = 0; i < n; ++i) {
    for (int j = i; j < n; ++j) {
      dist[i][j] = dist[j][i] = pts[i].Dist(pts[j]);
      dp[i][j] = dp[j][i] = dp2[i][j] = dp2[j][i] = 1e18;
//      if (i != j) ans[i][j] = {i, j}, ans[j][i] = {j, i};
//      else ans[i][j] = {i};
    }
  }
  Divide(0, n - 1);
  
  int lim = Mid(0, n - 1);
  double ans = 1e18;
  int start = -1, fin = -1;
  for (int i = 0; i < lim; ++i) {
    for (int j = lim; j < n; ++j) {
      if (Min(ans, dp[i][j])) {
        start = i;
        fin = j;
      }
    }
  }
  cout << fixed << setprecision(10) << ans << endl;
  Reconstr(start, fin);
  cout << endl;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 0
Memory Limit Exceeded

input:

8
7 3
2 0
4 5
1 4
8 2
9 9
0 8
6 1

output:

26.3833257716

result: