凸包
约 33 个字 56 行代码 预计阅读时间 1 分钟
二维凸包是橡皮筋包住木板上所有钉子后的形状,编程用凸包上的点描述凸包
typedef double db;
const db EPS = 1e-9;
inline int sign(db a) { return a < -EPS ? -1 : a > EPS; }
inline int cmp(db a, db b) { return sign(a - b); }
#define cross(p1, p2, p3) ((p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y))
#define crossOp(p1, p2, p3) sign(cross(p1, p2, p3))
struct P
{
db x, y;
P operator-(P p) { return {x - p.x, y - p.y}; }
bool operator<(P p) const
{
int c = cmp(x, p.x);
if (c)
return c == -1;
return cmp(y, p.y) == -1;
}
db distTo(P p) { return (*this - p).abs(); }
db abs() { return sqrt(abs2()); }
db abs2() { return x * x + y * y; }
};
vector<P> convexHull(vector<P> ps)
{
int n = ps.size();
if (n <= 1)
return ps;
sort(ps.begin(), ps.end());
vector<P> qs(n * 2);
int k = 0;
for (int i = 0; i < n; qs[k++] = ps[i++])
while (k > 1 && crossOp(qs[k - 2], qs[k - 1], ps[i]) <= 0)
--k;
for (int i = n - 2, t = k; i >= 0; qs[k++] = ps[i--])
while (k > t && crossOp(qs[k - 2], qs[k - 1], ps[i]) <= 0)
--k;
qs.resize(k - 1);
return qs;
}
vector<P> convexHullNonStrict(vector<P> ps)
{
// caution: need to unique the Ps first
int n = ps.size();
if (n <= 1)
return ps;
sort(ps.begin(), ps.end());
vector<P> qs(n * 2);
int k = 0;
for (int i = 0; i < n; qs[k++] = ps[i++])
while (k > 1 && crossOp(qs[k - 2], qs[k - 1], ps[i]) < 0)
--k;
for (int i = n - 2, t = k; i >= 0; qs[k++] = ps[i--])
while (k > t && crossOp(qs[k - 2], qs[k - 1], ps[i]) < 0)
--k;
qs.resize(k - 1);
return qs;
}