1. 程式人生 > >【最小圓覆蓋 模板】HDU

【最小圓覆蓋 模板】HDU

Problem Description

Each person had do something foolish along with his or her growth.But,when he or she did this that time,they could not predict that this thing is a mistake and they will want this thing would rather not happened. The world king Sconbin is not the exception.One day,Sconbin was sleeping,then swakened by one nightmare.It turned out that his love letters to Dufein were made public in his dream.These foolish letters might ruin his throne.Sconbin decided to destroy the letters by the military exercises's opportunity.The missile is the best weapon.Considered the execution of the missile,Sconbin chose to use one missile with the minimum destruction. Sconbin had writen N letters to Dufein, she buried these letters on different places.Sconbin got the places by difficult,he wants to know where is the best place launch the missile,and the smallest radius of the burst area. Let's help Sconbin to get the award.

Input

There are many test cases.Each case consists of a positive integer N(N<500,^V^,our great king might be a considerate lover) on a line followed by N lines giving the coordinates of N letters.Each coordinates have two numbers,x coordinate and y coordinate.N=0 is the end of the input file.

Output

For each case,there should be a single line in the output,containing three numbers,the first and second are x and y coordinates of the missile to launch,the third is the smallest radius the missile need to destroy all N letters.All output numbers are rounded to the second digit after the decimal point.

Sample Input

3

1.00 1.00

2.00 2.00

3.00 3.00

0

Sample Output

2.00 2.00 1.41

題意:給幾個點,用一個最小的圓把這些點全部覆蓋,求這個圓的圓心半徑

思路:窮舉法,最小圓覆蓋必然是某三個頂點的外界圓,那麼設定三層迴圈進行列舉就可以了!

雖然演算法是o(n^3),但是實際執行大概是在o(n)左右

  但是會出現下面的例外。

  

  也就是說三層遍歷得到C(n,3)個外接圓,並不能夠保證演算法的正確性,我們還要構造C(n,2)個以兩個點的連線為直徑的圓。

  關於求解一個三角形的外接圓圓心:

  我們只需找到兩條線段的中垂線然後求交點即可。

#include <stdio.h>
#include <math.h>
#include <algorithm>
#define eps 1e-8
using namespace std;
 
struct point
{
	double x, y;
}p[510];
 
point o;
double r;
 
double dis(point a, point b)
{
	return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
 
void getcircle(point a, point b, point c)
{//求外心 
	double a1 = b.x - a.x, b1 = b.y - a.y, c1 = (a1 * a1 + b1 * b1) / 2;  
    double a2 = c.x - a.x, b2 = c.y - a.y, c2 = (a2 * a2 + b2 * b2) / 2;  
    double d = a1 * b2 - a2 * b1;  
    o.x = a.x + (c1 * b2 - c2 * b1) / d;  
    o.y = a.y + (a1 * c2 - a2 * c1) / d;
}
 
int main ()
{
	int n;
	while(scanf("%d", &n))
	{
		if(n == 0)
			break;
		for(int i = 0; i < n; i++)
			scanf("%lf %lf", &p[i].x, &p[i].y);
		r = 0.0;//半徑 
		o = p[0];//圓心
		for(int i = 1; i < n; i++)
		{
			if(dis(p[i], o) > r )
			{//先確定第一個點 
				r = 0.0;
				o = p[i];
				for(int j = 0; j < i; j++)
				{//確定第二個點 
					if(dis(p[j], o) > r )
					{
						o.x = (p[j].x + p[i].x) / 2.0;
						o.y = (p[j].y + p[i].y) / 2.0;
						r = dis(p[j], o);
						for(int k = 0; k < j; k++)
						{//如果還有點不在園內,那麼就是三個點的情況,確定第三個點 
							if(dis(p[k], o) > r)
							{
								getcircle(p[i], p[j], p[k]);
								r = dis(p[k], o);
							}
						}
					}
				}			
			}
		}
		printf("%.2lf %.2lf %.2lf\n", o.x, o.y, r);
	}
	return 0;
}