最小覆盖圆

描述

平面上n个点,包含这n个点(点可以在圆的边界)的圆称为这n个点的覆盖圆,求这n个点的半径最小的覆盖圆,输出该圆的圆心坐标和半径。

输入
第一行是整数n,表示点数。后面是n个点的坐标。0<n<5000

n

x1 y1
x2 y2
,
xn yn

输出
输出n个点的最小覆盖圆,圆心坐标和半径。保留五位小数

输入样例 1

3
0 0
0 3000
4000 0

输出样例 1
2000.00000 1500.00000 2500.00000

输入样例 2
9
200 400
300 400
300 300
400 300
400 400
500 400
500 200
350 200
200 200
输出样例 2
350.00000 300.00000 180.27756

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define eps 1e-8
using namespace std;

struct point{
	double x,y;
};

point c;
point p[5005];
double r;

double dist(point a,point b){
	return sqrt(pow((a.x-b.x),2)+pow((a.y-b.y),2));
}

void circle1(point a,point b){
	c.x=(a.x+b.x)/2;
	c.y=(a.y+b.y)/2;
	r=sqrt(pow((a.x-c.x),2)+pow((a.y-c.y),2));
} 

void circle2(point p1,point p2,point p3){
	//根据克拉默法则求外接圆的圆心坐标(x0,y0),以及半径r
	double a1 = 2*(p2.x - p1.x);
	double b1 = 2*(p2.y - p1.y);
	double c1 = p2.x*p2.x + p2.y*p2.y - p1.x*p1.x - p1.y*p1.y;
	double a2 = 2*(p3.x - p2.x);
	double b2 = 2*(p3.y - p2.y);
	double c2 = p3.x*p3.x + p3.y*p3.y - p2.x*p2.x - p2.y*p2.y;
	c.x = ((c1*b2) - (c2*b1)) / ((a1*b2) - (a2*b1));
	c.y = ((a1*c2) - (a2*c1)) / ((a1*b2) - (a2*b1));
		r = dist(c, p1);
}


main(){
	int n; cin >> n;
	for(int i=0;i<n;i++)
		cin>>p[i].x>>p[i].y;
	
	c=p[0];r=0;
	
	//试探边界 
	for(int i=1;i<n;i++)
	   if(dist(c,p[i])>r){//新点,不在原覆盖圆里 
	   	 circle1(p[0],p[i]);//寻找新覆盖圆 
	   	   for(int j=1;j<i;j++)
	   	      if(dist(c,p[j])>r){//判断原来的点是否在新的覆盖圆里 
	   	      	circle1(p[j],p[i]);//不在,产生新的覆盖圆 
	   	      	   for(int k=0;k<j;k++)
	   	      	      if(dist(c,p[k])>r)//若还不在则使用三个点来构造圆
	   	      	        circle2(p[k],p[i],p[j]);
			   }
	   } 
  
  printf("%.5lf %.5lf %.5lf",c.x,c.y,r);
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值