最小圆覆盖模板

例题:

https://www.luogu.com.cn/problem/P1742

讲解:

https://blog.csdn.net/wu_tongtong/article/details/79362339

关于求经过三点圆的一些注意事项:
三点共线时,取距离最大的两点作为圆的直径。

否则,求两条中垂线交点即可。

#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
#define ff(i, x, y) for(int i = x, B = y; i <  B; i ++)
#define fd(i, x, y) for(int i = x, B = y; i >= B; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;

#define db double

struct P {
	db x, y;	
	P(){}
	P(db _x, db _y) { x = _x, y = _y;}
};

struct L {
	P p, v;
	L(){}
	L(P _p, P _v) { p = _p, v = _v;}
};

struct C {
	P p; db r;
	C(){}
	C(P _p, db _r) { p = _p, r = _r;}
};

const db eps = 1e-10;

P operator + (P a, P b) { return P(a.x + b.x, a.y + b.y) ;}
P operator - (P a, P b) { return P(a.x - b.x, a.y - b.y);}
P operator * (P a, db b) { return P(a.x * b, a.y * b);}
P operator / (P a, db b) { return P(a.x / b, a.y / b);}
db operator ^ (P a, P b) { return a.x * b.y - a.y * b.x;}
db operator * (P a, P b) { return a.x * b.x + a.y * b.y;}
db len(P a) { return sqrt(a.x * a.x + a.y * a.y);}
db len2(P a) { return a.x * a.x + a.y * a.y;}
P x90(P a) { return P(-a.y, a.x);}
P jd(L a, L b) { return b.p + b.v * ((b.p - a.p) ^ a.v) / (a.v ^ b.v);};
L zcx(P a, P b) { return L((a + b) / 2, x90(b - a));}
C cir(P a, P b, P c) {
	C d;
	if(abs((b - a) ^ (c - a)) < eps) {
		db l1 = len(b - a), l2 = len(c - a), l3 = len(c - b);
		if(l1 >= l2 && l1 >= l3) {
			d.p = (a + b) / 2;
			d.r = len(d.p - a);
		} else
		if(l2 >= l3) {
			d.p = (a + c) / 2;
			d.r = len(d.p - a);
		} else {
			d.p = (b + c) / 2;
			d.r = len(d.p - b);
		}
	} else {
		d.p = jd(zcx(a, b), zcx(a, c));
		d.r = len(d.p - a);
	}
	return d;
}
int incir(C c, P a) {
	return len(a - c.p) <= c.r + eps;
}

const int N = 1e5 + 5;

int n;
P a[N];


int main() {
	srand(19260817);
	scanf("%d", &n);
	fo(i, 1, n) scanf("%lf %lf", &a[i].x, &a[i].y);
	random_shuffle(a + 1, a + n + 1);
	C c = C(a[1], 0);
	fo(i, 2, n) if(!incir(c, a[i])) {
		c = C(a[i], 0);
		fo(j, 1, i - 1) if(!incir(c, a[j])) {
			c = cir(a[i], a[i], a[j]);
			fo(k, 1, j - 1) if(!incir(c, a[k])) {
				c = cir(a[i], a[j], a[k]);
			}
		}
	}
	pp("%.10lf\n%.10lf %.10lf\n", c.r, c.p.x, c.p.y);
}
posted @ 2020-03-01 13:13  Cold_Chair  阅读(221)  评论(0编辑  收藏  举报