AIGC标识 凸包

using ll = long long;
struct Point {
    ll x, y;

    bool operator<(const Point &other) const {
        if (x != other.x) return x < other.x;
        return y < other.y;
    }

    bool operator==(const Point &other) const {
        return x == other.x && y == other.y;
    }
};

ll cross(const Point &O, const Point &A, const Point &B) {
    return (A.x - O.x) * (B.y - O.y)
           - (A.y - O.y) * (B.x - O.x);
}



// 求凸包
// keep_collinear = false:不保留边上的中间共线点
// keep_collinear = true :保留凸包边界上的共线点
vector<Point> convexHull(vector<Point> p, bool keep_collinear = false) {
    sort(p.begin(), p.end());
    p.erase(unique(p.begin(), p.end()), p.end());

    int n = p.size();

    if (n <= 1) {
        return p;
    }

    vector<Point> hull;

    // 下凸壳
    for (const auto &point : p) {
        while (hull.size() >= 2) {
            ll c = cross(hull[hull.size() - 2],
                         hull[hull.size() - 1],
                         point);

            if (keep_collinear ? c < 0 : c <= 0) {
                hull.pop_back();
            } else {
                break;
            }
        }
        hull.push_back(point);
    }

    // 上凸壳
    int lower_size = hull.size();

    for (int i = n - 2; i >= 0; --i) {
        while ((int)hull.size() > lower_size) {
            ll c = cross(hull[hull.size() - 2],
                         hull[hull.size() - 1],
                         p[i]);

            if (keep_collinear ? c < 0 : c <= 0) {
                hull.pop_back();
            } else {
                break;
            }
        }
        hull.push_back(p[i]);
    }

    hull.pop_back();

    return hull;
}
posted @ 2026-10-05 16:15  haze1231  阅读(6)  评论(0)    收藏  举报