ZOJ 1450

本文介绍了一个寻找包含所有给定点的最小圆的算法实现。通过随机重排输入点集并逐步迭代来确定圆心和半径,确保了所求圆能覆盖所有点且半径尽可能小。文中提供了完整的C++代码实现。

最小圆覆盖

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>

using namespace std;
const double eps=0.00000001;
struct point {
	double x,y;
}p[110];

struct circle{
	point cent;
	double rad;
}cir;
int n;

double TriangleArea(point t1,point t2,point t3){
	point p1,p2;
	p1.x=t1.x-t3.x; p1.y=t1.y-t3.y;
	p2.x=t2.x-t3.x; p2.y=t2.y-t3.y;
	return fabs(p1.x*p2.y-p2.x*p1.y)/2;
}

double dist(point p1,point p2){
	return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}

void TriangleCircle(point ta,point tb,point tc){
	double a=dist(ta,tb);
	double b=dist(tb,tc);
	double c=dist(tc,ta);
	cir.rad=(a*b*c)/TriangleArea(ta,tb,tc)/4;
	double xa=ta.x; double ya=ta.y;
	double xb=tb.x; double yb=tb.y;
	double xc=tc.x; double yc=tc.y;
	double c1=(xa*xa+ya*ya-xb*xb-yb*yb)/2;
	double c2=(xa*xa+ya*ya-xc*xc-yc*yc)/2;
	cir.cent.x=(c1*(ya-yc)-c2*(ya-yb))/((xa-xb)*(ya-yc)-(xa-xc)*(ya-yb));
	cir.cent.y=(c1*(xa-xc)-c2*(xa-xb))/((ya-yb)*(xa-xc)-(ya-yc)*(xa-xb));
}

void slove(){
	random_shuffle(p,p+n);
	cir.cent=p[0]; cir.rad=0;
	for(int i=1;i<n;i++){
		if(dist(p[i],cir.cent)-eps>cir.rad	){
			cir.cent=p[i]; cir.rad=0;
			for(int j=0;j<i;j++){
				if(dist(p[j],cir.cent)-eps>cir.rad	){
					cir.cent.x=(p[j].x+p[i].x)/2;
					cir.cent.y=(p[i].y+p[j].y)/2;
					cir.rad=dist(p[j],p[i])/2;
					for(int k=0;k<j;k++){
						if(dist(p[k],cir.cent)-eps>cir.rad	){
							TriangleCircle(p[i],p[j],p[k]);
						}
					}
				}
			}
		}
	}
}

int main(){
	while(scanf("%d",&n)!=EOF){
		if(n==0) break;
		for(int i=0;i<n;i++){
			scanf("%lf%lf",&p[i].x,&p[i].y);
		}
		slove();
		printf("%0.2f %0.2f %0.2f\n",cir.cent.x,cir.cent.y,cir.rad);
	}
	return 0;
}

  

转载于:https://www.cnblogs.com/jie-dcai/p/3885931.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值