Bao lồi (Convex Hull)

Convex Hull - Kattis

#include <bits/stdc++.h>

using namespace std;

#define Point Vector
struct Vector {
    int x, y;
    Vector() { x = y = 0; }
    Vector(int xx, int yy) {
        x = xx; y = yy;
    }
    Vector operator - (const Vector &v) const {
        return Vector(x-v.x,y-v.y);
    }
    long long operator % (const Vector &v) const {
        return 1LL * x * v.y - 1LL * y * v.x;
    }
    friend istream& operator >> (istream&is, Vector &v) {
        is >> v.x >> v.y;
        return is;
    }
    friend ostream& operator << (ostream&os, const Vector &v) {
        os << v.x << ' ' << v.y;
        return os;
    }
    bool operator == (const Vector &v) const {
        return x == v.x && y == v.y;
    }
    bool operator < (const Vector &v) const {
        return make_pair(x,y) < make_pair(v.x,v.y);
    }
    friend bool CCW(const Point &a, const Point &b, const Point &c) {
        return (b-a) % (c-b) > 0;
    }
    friend bool CW(const Point &a, const Point &b, const Point &c) {
        return (b-a) % (c-b) < 0;
    }
};

int numPoint;
vector<Point> points;

vector<Point> ConvexHull(vector<Point> points) {
    sort(points.begin(),points.end());
    points.resize(unique(points.begin(),points.end()) - points.begin());
    if (points.size() <= 2) return points;
    vector<Point> up, down;
    Point lef = points[0];
    Point rig = points.back();
    for (int i = 0; i < points.size(); ++i) {
        if (i==0 || i+1==points.size() || CW(lef, points[i], rig)) {
            while (up.size() > 1 && !CW(up[(int)up.size()-2], up.back(), points[i])) {
                up.pop_back();
            }
            up.push_back(points[i]);
        }
        if (i==0 || i+1==points.size() || CCW(lef, points[i], rig)) {
            while (down.size() > 1 && !CCW(down[(int)down.size()-2], down.back(), points[i])) {
                down.pop_back();
            }
            down.push_back(points[i]);
        }
    }
    // Counter clockwise
    for (int i = (int)up.size()-2; i > 0; --i) {
        down.push_back(up[i]);
    }
    return down;
}

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    while ((cin >> numPoint) && numPoint != 0) {
        points.resize(numPoint);
        for (int i = 0; i < numPoint; ++i) {
            cin >> points[i];
        }
        vector<Point> hull = ConvexHull(points);
        cout << hull.size() << '\n';
        for (int i = 0; i < hull.size(); ++i) {
            cout << hull[i] << '\n';
        }
    }
    return 0;
}

Convex Hull - CSES

#include <bits/stdc++.h>

using namespace std;

#define Point Vector
struct Vector {
    int x, y;
    Vector() { x = y = 0; }
    Vector(int xx, int yy) {
        x = xx; y = yy;
    }
    Vector operator - (const Vector &v) const {
        return Vector(x-v.x,y-v.y);
    }
    long long operator % (const Vector &v) const {
        return 1LL * x * v.y - 1LL * y * v.x;
    }
    friend istream& operator >> (istream&is, Vector &v) {
        is >> v.x >> v.y;
        return is;
    }
    friend ostream& operator << (ostream&os, const Vector &v) {
        os << v.x << ' ' << v.y;
        return os;
    }
    bool operator < (const Vector &v) const {
        return make_pair(x,y) < make_pair(v.x,v.y);
    }
    friend bool CCW(const Point &a, const Point &b, const Point &c) {
        return (b-a) % (c-b) > 0;
    }
    friend bool CW(const Point &a, const Point &b, const Point &c) {
        return (b-a) % (c-b) < 0;
    }
};

int numPoint;
vector<Point> points;

vector<Point> ConvexHull(vector<Point> points) {
    if (points.size() <= 2) return points;
    sort(points.begin(),points.end());
    vector<Point> up, down;
    Point lef = points[0];
    Point rig = points.back();
    for (int i = 0; i < points.size(); ++i) {
        if (!CCW(lef, points[i], rig)) {
            while (up.size() > 1 && CCW(up[(int)up.size()-2], up.back(), points[i])) {
                up.pop_back();
            }
            up.push_back(points[i]);
        }
        if (!CW(lef, points[i], rig)) {
            while (down.size() > 1 && CW(down[(int)down.size()-2], down.back(), points[i])) {
                down.pop_back();
            }
            down.push_back(points[i]);
        }
    }
    // Clockwise
    for (int i = (int)down.size()-2; i > 0; --i) {
        up.push_back(down[i]);
    }
    return up;
}

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    cin >> numPoint;
    points.resize(numPoint);
    for (int i = 0; i < numPoint; ++i) {
        cin >> points[i];
    }
    vector<Point> hull = ConvexHull(points);
    cout << hull.size() << '\n';
    for (int i = 0; i < hull.size(); ++i) {
        cout << hull[i] << '\n';
    }
    return 0;
}

Độ phức tạp: \(O(Nlog(N))\)

Đọc thêm