zoj 1450 Minimal Circle(最小覆盖圆)

详见http://archive.cnblogs.com/a/1875149/

我在纸上画了一遍,成功找到圆心~~~这个蛮好理解的,自己画一遍就出来了。

测试了下时间复杂度,1.1W的点,最多循环次数在10+W,最少的2W左右,上面文章里也有简单证明,这个算法是O(n)的

后查了多个博客的算法,发现加个random_shuffle(p,p+n); 快了好多。可能数据不够随机吧。而且在BZOJ的这个题,如果不随机,就过不去,估计是因为不是随机的,交换次数多然后精度损失了。BZOJ的数据卡精度的。


#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>

using namespace std;

const int MAX = 110;
struct point{ double x,y;};
point p[MAX];
const double eps = 1e-6;
bool dy(double x,double y)	{	return x > y + eps;}	// x > y 
bool xy(double x,double y)	{	return x < y - eps;}	// x < y 
bool dyd(double x,double y)	{ 	return x > y - eps;}	// x >= y 
bool xyd(double x,double y)	{	return x < y + eps;} 	// x <= y 
bool dd(double x,double y) 	{	return fabs( x - y ) < eps;}  // x == y
double disp2p(point a,point b) 
{
	return sqrt( ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ) );
}
point l2l_inst_p(point u1,point u2,point v1,point v2)
{
	point ans = u1;
	double t = ((u1.x - v1.x)*(v1.y - v2.y) - (u1.y - v1.y)*(v1.x - v2.x))/
				((u1.x - u2.x)*(v1.y - v2.y) - (u1.y - u2.y)*(v1.x - v2.x));
	ans.x += (u2.x - u1.x)*t;
	ans.y += (u2.y - u1.y)*t;
	return ans;
}
point circumcenter(point a,point b,point c)
{
	point ua,ub,va,vb;
	ua.x = ( a.x + b.x )/2;
	ua.y = ( a.y + b.y )/2;
	ub.x = ua.x - a.y + b.y;//根据 垂直判断,两线段点积为0 
	ub.y = ua.y + a.x - b.x;
	va.x = ( a.x + c.x )/2;
	va.y = ( a.y + c.y )/2;
	vb.x = va.x - a.y + c.y;
	vb.y = va.y + a.x - c.x;
	return l2l_inst_p(ua,ub,va,vb);
} 
void min_circle(point p[],int n,point &c,double &r)
{
	random_shuffle(p,p+n); // 重点 
	c = p[0]; r = 0;
	int cnt = 0;
	for(int i=1; i<n; i++)
		if( dy(disp2p(p[i],c),r) )
		{
			c = p[i]; r = 0;
			for(int k=0; k<i; k++)
				if( dy(disp2p(p[k],c),r) )
				{
					c.x = (p[i].x + p[k].x)/2;
					c.y = (p[i].y + p[k].y)/2;
					r = disp2p(p[k],c);
					for(int j=0; j<k; j++)
						if( dy(disp2p(p[j],c),r) )
						{							// 求外接圆圆心,三点必不共线 
							c = circumcenter(p[i],p[k],p[j]);
							r = disp2p(p[i],c);
						}
				}
		}
}
			
int main()
{
	int n;
	
	while( ~scanf("%d",&n) && n )
	{
		for(int i=0; i<n; i++)
			scanf("%lf%lf",&p[i].x,&p[i].y);
		point c; double r;
		min_circle(p,n,c,r);
		printf("%.2lf %.2lf %.2lf\n",c.x,c.y,r);
	}
return 0;
}


你可能感兴趣的:(zoj 1450 Minimal Circle(最小覆盖圆))