Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <cmath>
- using namespace std;
- typedef pair<long long, long long> pll;
- long long getOrientation(pll &a, pll &b, pll &c) {
- return a.first * b.second + b.first * c.second + c.first * a.second - c.first * b.second - b.first * a.second - a.first * c.second;
- }
- vector<pll> getConvexHull(vector<pll> &points) {
- vector<pll> hull;
- int leftmost = 0;
- int n = int(points.size());
- for (int i = 1; i < n; ++i) {
- if (points[i].first < points[leftmost].first) {
- leftmost = i;
- }
- }
- int current = leftmost, s;
- do {
- hull.push_back(points[current]);
- s = (current + 1) % n;
- for (int i = 0; i < n; ++i) {
- if (getOrientation(points[current], points[s], points[i]) < 0) {
- s = i;
- }
- }
- current = s;
- } while (current != leftmost);
- return hull;
- }
- double distance(pll &a, pll &b) {
- return sqrt((b.first - a.first) * (b.first - a.first) + (b.second - a.second) * (b.second - a.second));
- }
- bool findPoint(pll &point, vector<pll> &hull) {
- for (auto &p : hull) {
- if (point == p) {
- return true;
- }
- }
- return false;
- }
- double getDistance1(pll &i, pll &j, pll &r) {
- return distance(i, r) + distance(r, j) - distance(i, j);
- }
- double getDistance2(pll &i, pll &j, pll &r) {
- return (distance(i, r) + distance(r, j)) / distance(i, j);
- }
- pair<pll, pll> findClosest(pll &r, vector<pll> &hull) {
- double minDist = 1 << 30;
- pair<pll, pll> ans;
- for (auto i = 1; i < hull.size(); ++i) {
- double dist = getDistance1(hull[i - 1], hull[i], r);
- if (dist < minDist) {
- minDist = dist;
- ans = {hull[i - 1], hull[i]};
- }
- }
- double dist = getDistance1(hull[hull.size() - 1], hull[0], r);
- if (dist < minDist) {
- minDist = dist;
- ans = {hull[hull.size() - 1], hull[0]};
- }
- return ans;
- }
- int main() {
- int n, x, y;
- vector<pll> points;
- cin >> n;
- for (int i = 1; i <= n; ++i) {
- cin >> x >> y;
- points.emplace_back(x, y);
- }
- bool inHull[n];
- auto hull = getConvexHull(points);
- for (auto i = 0; i < points.size(); ++i) {
- if (findPoint(points[i], hull)) {
- inHull[i] = true;
- }
- }
- int count = int(points.size() - hull.size());
- while (count) {
- vector<pair<pair<pll, pll>, int>> candidates;
- for (auto i = 0; i < points.size(); ++i) {
- if (!inHull[i]) {
- auto p = findClosest(points[i], hull);
- candidates.emplace_back(p, i);
- }
- }
- double minDist = 1 << 30;
- pair<pair<pll, pll>, int> bestCandidate;
- for (auto &c : candidates) {
- auto dist = getDistance2(c.first.first, c.first.second, points[c.second]);
- if (dist < minDist) {
- minDist = dist;
- bestCandidate = c;
- }
- }
- hull.push_back(points[bestCandidate.second]);
- inHull[bestCandidate.second] = true;
- --count;
- for (auto i = 0; i < hull.size() - 2; ++i) {
- if (hull[i] == bestCandidate.first.first) {
- for (auto j = hull.size() - 1; j > i; --j) {
- hull[j] = hull[j - 1];
- }
- hull[i + 1] = points[bestCandidate.second];
- break;
- }
- }
- }
- hull.push_back(hull.front());
- for (auto &p : hull) {
- cout << p.first << ' ' << p.second << '\n';
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment