1. 程式人生 > >最小圓覆蓋 三分套三分 可以拓展為球

最小圓覆蓋 三分套三分 可以拓展為球

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

using namespace std;

const int maxn = 10000;
const double eps = 1e-11;
double minx, miny, maxx, maxy;
struct Point
{
	double x, y;
	Point() {}
	Point(double _x, double _y)
	{
		x = _x;
		y = _y;
	}
	Point operator -(const Point &b)const
	{
		return Point(x - b.x, y - b.y);
	}
	double operator *(const Point &b)const
	{
		return x * b.x + y * b.y;
	}
};

Point p[maxn];
int T;

double dist(Point a, Point b)
{
	Point x = a - b;
	return sqrt(x * x);
}

double f(double x, double y)
{
	Point ans1 = Point(x, y);
	double sum = -1.0;
	for (int i = 0; i<T; i++)
	{
		sum = max(dist(ans1, p[i]), sum);
	}
	return sum;
}
double three_search2(double x)
{
	double l = miny, r = maxy;
	while (r - l>eps)
	{
		double lmid = l + (r - l) / 3;
		double rmid = r - (r - l) / 3;
		if (f(x, lmid) >= f(x, rmid))
		{
			l = lmid;
		}
		else
		{
			r = rmid;
		}
	}
	return l;
}

Point three_search()
{
	double l = minx, r= maxx;
	while (r - l>eps)
	{
		double lmid = l + (r - l) / 3;
		double rmid = r - (r - l) / 3;
		if (f(lmid, three_search2(lmid)) >= f(rmid, three_search2(rmid)))
		{
			l = lmid;
		}
		else
		{
			r = rmid;
		}
	}
	return Point(l, three_search2(l));
}

int main()
{
	while (1)
	{
		scanf("%d", &T);
		if (T == 0)
			break;
		minx = 1000000.0,maxx= -1000000.0;
		miny = 1000000.0, maxy = -1000000.0;
		for (int i = 0; i<T; i++)
		{
			scanf("%lf %lf", &p[i].x, &p[i].y);
			minx = min(minx, p[i].x), maxx = max(maxx, p[i].x);
			miny = min(miny, p[i].y), maxy = max(maxy, p[i].y);
		}
		Point ans = three_search();
		printf("%.2lf %.2lf %.2lf\n", ans.x, ans.y, f(ans.x, ans.y));

	}
	return 0;
}