Problem p02303 (C++) — buggy submission, verdict: Time Limit Exceeded


#include <algorithm>
#include <cmath>
#include <vector>

const double INF = 1e9;
const double EPS = 1e-9;

struct Point {
  Point() : x(INF), y(INF) {}
  Point(double x, double y) : x(x), y(y) {}
  double x, y;
};
struct Compare {
  bool f;
  Compare(bool f = false) : f(f) {}
  bool operator()(const Point &lhs, const Point &rhs) const {
    return f ? lhs.y < rhs.y : lhs.x < rhs.x;
  }
};
double distance(const Point &lhs, const Point &rhs) {
  return std::hypot(lhs.x - rhs.x, lhs.y - rhs.y);
}

struct Result {
  double d;
  Point p1, p2;
  Result() : d(INF) {}
  Result(double d, const Point p1, const Point p2) : d(d), p1(p1), p2(p2) {}
};
bool operator<(const Result &lhs, const Result &rhs) { return lhs.d < rhs.d; }

Result closest_pair_recursion(const std::vector<Point>::const_iterator &begin,
                              const std::vector<Point>::const_iterator &end) {
  int size = end - begin;
  if (size <= 1)
    return Result();

  auto mid = begin + size / 2;
  Result r = std::min(closest_pair_recursion(begin, mid),
                      closest_pair_recursion(mid, end));

  auto left = std::lower_bound(begin, end, Point(mid->x - r.d - EPS, mid->y),
                               Compare());
  auto right =
      std::upper_bound(left, end, Point(mid->x + r.d + EPS, mid->y), Compare());
  std::vector<Point> y_sorted(left, right);
  std::sort(y_sorted.begin(), y_sorted.end(), Compare(true));

  for (auto i = y_sorted.begin(); i != y_sorted.end(); ++i) {
    for (auto j = i + 1; j != y_sorted.end(); ++j) {
      if (j->y - i->y >= r.d)
        break;
      if (distance(*i, *j) >= r.d)
        continue;
      r = Result(distance(*i, *j), *i, *j);
    }
  }
  //     // y 座標の差が r.d 以上になる点を予め計算：微妙に遅い
  //     for(auto i = y_sorted.begin(); i != y_sorted.end(); ++i) {
  //         auto top = std::upper_bound(i + 1, y_sorted.end(), Point(i->x, i->y
  //         + r.d + EPS), Compare(true)); for(auto j = i + 1; j != top; ++j) {
  //             if(distance(*i, *j) >= r.d) continue;
  //             r = Result(distance(*i, *j), *i, *j);
  //         }
  //     }

  return r;
}
Result closest_pair(std::vector<Point> point) {
  std::sort(point.begin(), point.end(), Compare());
  return closest_pair_recursion(point.begin(), point.end());
}

////////////////////////////////////////////////////////////////////////////////
#include <iomanip>
#include <iostream>
using namespace std;

int main() {
  int n;
  vector<Point> v;
  for (cin >> n; n > 0; --n) {
    double x, y;
    cin >> x >> y;
    v.push_back(Point(x, y));
  }
  auto res = closest_pair(v);
  cout << setprecision(12) << fixed << res.d << endl;
}

Error: TLE

Fixed submission:


#include <algorithm>
#include <cmath>
#include <vector>

struct Point {
  double x, y;
  Point(double x, double y) : x(x), y(y) {}
};
bool operator<(const Point &lhs, const Point &rhs) {
  return lhs.x != rhs.x ? lhs.x < rhs.x : lhs.y < rhs.y;
}
double distance(const Point &lhs, const Point &rhs) {
  return std::hypot(lhs.x - rhs.x, lhs.y - rhs.y);
}

std::vector<Point> closest_pair(std::vector<Point> point) {
  std::sort(point.begin(), point.end());
  int i1 = 0, i2 = 1;
  int candidate[point.size()], candidate_size = 0;
  candidate[candidate_size++] = i1;
  candidate[candidate_size++] = i2;
  double d = distance(point[i1], point[i2]);
  for (int i = 2; i < point.size(); candidate[candidate_size++] = i++)
    for (int j = 0; j < candidate_size; ++j) {
      if (distance(point[i], point[candidate[j]]) < d)
        d = distance(point[i1 = i], point[i2 = candidate[j]]);
      if (point[i].x - point[candidate[j]].x >= d)
        candidate[j--] = candidate[--candidate_size];
    }
  return {point[i1], point[i2]};
}
////////////////////////////////////////////////////////////////////////////////
#include <iomanip>
#include <iostream>
using namespace std;

int main() {
  int n;
  vector<Point> v;
  for (cin >> n; n > 0; --n) {
    double x, y;
    cin >> x >> y;
    v.push_back(Point(x, y));
  }
  auto res = closest_pair(v);
  cout << setprecision(12) << fixed << distance(res[0], res[1]) << endl;
}