On this page
article
Minimum Enclosing Circle
Sobre
O(n) com alta probabilidade
Link original: minCirc.cpp
Código
const double EPS = 1e-12;
mt19937 rng((int) chrono::steady_clock::now().time_since_epoch().count());
struct pt {
double x, y;
pt(double x_ = 0, double y_ = 0) : x(x_), y(y_) {}
pt operator + (const pt& p) const { return pt(x+p.x, y+p.y); }
pt operator - (const pt& p) const { return pt(x-p.x, y-p.y); }
pt operator * (double c) const { return pt(x*c, y*c); }
pt operator / (double c) const { return pt(x/c, y/c); }
};
double dot(pt p, pt q) { return p.x*q.x+p.y*q.y; }
double cross(pt p, pt q) { return p.x*q.y-p.y*q.x; }
double dist(pt p, pt q) { return sqrt(dot(p-q, p-q)); }
pt center(pt p, pt q, pt r) {
pt a = p-r, b = q-r;
pt c = pt(dot(a, p+r)/2, dot(b, q+r)/2);
return pt(cross(c, pt(a.y, b.y)), cross(pt(a.x, b.x), c)) / cross(a, b);
}
struct circle {
pt cen;
double r;
circle(pt cen_, double r_) : cen(cen_), r(r_) {}
circle(pt a, pt b, pt c) {
cen = center(a, b, c);
r = dist(cen, a);
}
bool inside(pt p) { return dist(p, cen) < r+EPS; }
};
circle minCirc(vector<pt> v) {
shuffle(v.begin(), v.end(), rng);
circle ret = circle(pt(0, 0), 0);
for (int i = 0; i < v.size(); i++) if (!ret.inside(v[i])) {
ret = circle(v[i], 0);
for (int j = 0; j < i; j++) if (!ret.inside(v[j])) {
ret = circle((v[i]+v[j])/2, dist(v[i], v[j])/2);
for (int k = 0; k < j; k++) if (!ret.inside(v[k]))
ret = circle(v[i], v[j], v[k]);
}
}
return ret;
}