最小圆覆盖

求一个半径最小的圆使其内部至少包含 m 个点

#include <bits/stdc++.h>
using namespace std;
 
#define Mn 305
const double eps = 1e-7;
const double pi = acos(-1.0);
struct Point
{
	double x,y;
	Point() {}
	Point(double tx,double ty)
	{
		x=tx;
		y=ty;
	}
} p[Mn+5];
struct Node
{
	double angle;
	bool in;
} arc[Mn * Mn + 5];
int n;
double dist(Point p1,Point p2)
{
	return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
bool cmp(Node &n1,Node &n2)
{
	return n1.angle<n2.angle;
}
double R;
 
int MaxCircleCover()
{
    int ans=1;
    for(int i=0;i<n;i++)
	{
        int cnt=0;
        for(int j=0;j<n;j++)
		{
            if(i==j) continue;
            double D = dist(p[i],p[j]);
            if(D>2.0*R) continue;
            
            double angle=atan2(p[i].y-p[j].y,p[i].x-p[j].x);
            if(angle < 0)
                angle += 2 * pi;
                
            double phi=acos(D/(2.0*R));
            arc[cnt].angle=angle-phi+ 2 * pi;arc[cnt++].in=true;
            arc[cnt].angle=angle+phi+ 2 * pi;arc[cnt++].in=false;
        }
        sort(arc,arc+cnt,cmp);
        int tmp=1;
        for(int j=0;j<cnt;j++)
		{
            if(arc[j].in)  tmp++;
            else tmp--;
            ans=max(ans,tmp);
        }
    }
    return ans;
}
 
int main()
{
	int t;scanf("%d",&t);
	while(t--)
	{
		int s;
		scanf("%d%d",&n,&s);
		for(int i=0;i<n;i++)
			scanf("%lf%lf",&p[i].x,&p[i].y);
		double r;
		scanf("%lf",&r);
		double l1=0,r1=100000;	
		while(abs(r1-l1)>eps)
		{
			double mid=(l1+r1)*0.5;
			R=mid;
			int p=MaxCircleCover();
			if(p>=s)
			{
				r1=mid;
			}
			else
			{
				l1=mid;
			}
		}
		printf("%.4lf\n",l1+r);
	}
	return 0;
}

 

posted @ 2018-09-13 23:13  楼主好菜啊  阅读(125)  评论(0编辑  收藏  举报