列表

详情


NC243848. 最小圆覆盖

描述

给出N个点,让你画一个最小的包含所有点的圆。

输入描述

第一行一个整数 N 表示点的个数。

接下来 N 行每行两个实数 x_i,y_i 表示点的坐标。最多两位小数。

对于 的数据,

输出描述

第一行一个实数表示圆的半径。

第二行两个实数表示圆心的坐标。

本题开启 spj,您的答案与标准答案误差不超过 时,视为正确。

示例1

输入:

6
8.0 9.0
4.0 7.5
1.0 2.0
5.1 8.7
9.0 2.0
4.5 1.0

输出:

5.0000000000
5.0000000000 5.0000000000

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

pypy3 解法, 执行用时: 569ms, 内存消耗: 70100K, 提交时间: 2023-04-07 18:56:01

import sys
import math

def euclidean_distance(p1, p2):
    return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)

def make_circle(points):
    shuffled = list(points)
    circle = (0, 0, 0)
    for i, p in enumerate(shuffled):
        if is_inside_circle(circle, p):
            continue
        circle = (p[0], p[1], 0)
        for j, q in enumerate(shuffled[:i]):
            if is_inside_circle(circle, q):
                continue
            circle = ((p[0] + q[0]) / 2, (p[1] + q[1]) / 2, euclidean_distance(p, q) / 2)
            for k, r in enumerate(shuffled[:j]):
                if is_inside_circle(circle, r):
                    continue
                circle = make_circumcircle(p, q, r)
    return circle

def is_inside_circle(circle, point):
    center, radius = (circle[0], circle[1]), circle[2]
    return euclidean_distance(center, point) <= radius

def make_circumcircle(p1, p2, p3):
    d = 2 * (p1[0] * (p2[1] - p3[1]) + p2[0] * (p3[1] - p1[1]) + p3[0] * (p1[1] - p2[1]))
    ux = ((p1[0] ** 2 + p1[1] ** 2) * (p2[1] - p3[1]) + (p2[0] ** 2 + p2[1] ** 2) * (p3[1] - p1[1]) + (p3[0] ** 2 + p3[1] ** 2) * (p1[1] - p2[1])) / d
    uy = ((p1[0] ** 2 + p1[1] ** 2) * (p3[0] - p2[0]) + (p2[0] ** 2 + p2[1] ** 2) * (p1[0] - p3[0]) + (p3[0] ** 2 + p3[1] ** 2) * (p2[0] - p1[0])) / d
    r = euclidean_distance((ux, uy), p1)
    return (ux, uy, r)

def main():
    N = int(input().strip())
    points = [tuple(map(float, input().strip().split())) for _ in range(N)]

    circle = make_circle(points)
    print("{:.10f}".format(circle[2]))
    print("{:.10f} {:.10f}".format(circle[0], circle[1]))

if __name__ == "__main__":
    main()

C++(g++ 7.5.0) 解法, 执行用时: 169ms, 内存消耗: 3536K, 提交时间: 2023-03-15 20:25:40

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
struct node{
	double x,y;
}a[maxn];
double r;
node o;
double dis(node x,node y){
	return sqrt((x.x-y.x)*(x.x-y.x)+(y.y-x.y)*(y.y-x.y));
}
void work(node p1,node p2,node p3){
	double a,b,c,d,e,f;
	a=p2.y-p1.y;
	b=p3.y-p1.y;
	c=p2.x-p1.x;
	d=p3.x-p1.x;
	f=p3.x*p3.x+p3.y*p3.y-p1.x*p1.x-p1.y*p1.y;
	e=p2.x*p2.x+p2.y*p2.y-p1.x*p1.x-p1.y*p1.y;
	o.x=(a*f-b*e)/(2*a*d-2*b*c);
	o.y=(d*e-c*f)/(2*a*d-2*b*c);
	r=dis(o,p1);
}
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].x>>a[i].y;
	}
	random_shuffle(a+1,a+n+1);
	for(int i=1;i<=n;i++){
		if(dis(o,a[i])>r){
			o=a[i],r=0;
			for(int j=1;j<=i-1;j++){
				if(dis(o,a[j])>r){
					o.x=(a[i].x+a[j].x)/2;
					o.y=(a[i].y+a[j].y)/2;
					r=dis(o,a[j]);
					for(int k=1;k<=j-1;k++){
						if(dis(o,a[k])>r){
							work(a[i],a[j],a[k]);
						}
					}
				}
			}
		}
	}
	printf("%.10f\n%.10f %.10f",r,o.x,o.y);
	return 0;
}

上一题