P1742 最小圆覆盖 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
随机增量法
对于第 (i) 个点来说,若它在前 (i - 1) 个点的最小圆上,则不需要更新,否则,这个点一定在新的圆上。
枚举另外两个点
圆 C;
for(i=1 to n)
{
if(P[i] 不在 C 内)
{
C = {P[i], 0};
for(j=1 to i-1)
{
if(P[j] 不在 C 内)
{
C = {0.5*(P[i]+P[j]), 0.5*dist(P[i], P[j])};
for(k=1 to j-1)
{
if(P[k] 不在 C 内)
{
C = 外接圆(P[i], P[j], P[k]);
}
}
}
}
}
}
#include<bits/stdc++.h>
#define eps 1e-8
using namespace std;
struct point {
double x, y;
point operator + (const point& b)const {
return { x + b.x,y + b.y };
}
point operator / (const double b)const {
return { x / b,y / b };
}
}p[100005], o;
int n;
double r;
inline double sqr(double x) { return x * x; }
inline double dis(point a, point b){
return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));
}
inline bool cmp(double a, double b){
return fabs(a - b) < eps;
}
point geto(point a, point b, point c){
double a1, a2, b1, b2, c1, c2;
point ans;
a1 = 2 * (b.x - a.x), b1 = 2 * (b.y - a.y), c1 = sqr(b.x) - sqr(a.x) + sqr(b.y) - sqr(a.y);
a2 = 2 * (c.x - a.x), b2 = 2 * (c.y - a.y), c2 = sqr(c.x) - sqr(a.x) + sqr(c.y) - sqr(a.y);
if (cmp(a1, 0)){
ans.y = c1 / b1;
ans.x = (c2 - ans.y * b2) / a2;
}
else if (cmp(b1, 0)){
ans.x = c1 / a1;
ans.y = (c2 - ans.x * a2) / b2;
}
else{
ans.x = (c2 * b1 - c1 * b2) / (a2 * b1 - a1 * b2);
ans.y = (c2 * a1 - c1 * a2) / (b2 * a1 - b1 * a2);
}
return ans;
}
bool judge(point a) {
return dis(o, a) < r || cmp(dis(o, a), r);
}
int main(){
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%lf%lf", &p[i].x, &p[i].y);
random_shuffle(p + 1, p + 1 + n);
o = p[1];
for (int i = 1; i <= n; i++){
if (judge(p[i]))continue;
o = (p[i] + p[1]) / 2; r = dis(p[i], p[1]) / 2;
for (int j = 1; j < i; j++){
if (judge(p[j]))continue;
o = (p[i] + p[j]) / 2; r = dis(p[i], p[j]) / 2;
for (int k = 1; k < j; k++){
if (judge(p[k]))continue;
o = geto(p[i], p[j], p[k]);
r = dis(o, p[i]);
}
}
}
printf("%.10lf
%.10lf %.10lf", r, o.x, o.y);
}