zoukankan      html  css  js  c++  java
  • bzoj 1337 最小圆覆盖

    bzoj 1337 最小圆覆盖

    • 补充一个求三角形外心的向量法.用了点积的几何意义,很实用.出处.

      向量法求外心

    • 使用随机增量法求.首先随机打乱顺序,然后三重循环,选择当前在圆外的点更新圆,分别按照 (1/2/3) 个点确定圆的方式更新即可.

    • 由于随机一个点不在前 (i) 个点的最小覆盖圆内的概率是 (frac 3 i) ,可以证明这样的时间复杂度是 (O(n)) 的,这种做法可以推广到常数维度上,时间复杂度仍为 (O(n)) .

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define mp make_pair
    #define pii pair<int,int>
    inline int read()
    {
    	int x=0;
    	bool pos=1;
    	char ch=getchar();
    	for(;!isdigit(ch);ch=getchar())
    		if(ch=='-')
    			pos=0;
    	for(;isdigit(ch);ch=getchar())
    		x=x*10+ch-'0';
    	return pos?x:-x;
    }
    const double eps=1e-9;
    const int MAXN=1e5+10;
    int dcmp(double x)
    {
    	return fabs(x)<=eps?0:(x>0?1:-1);
    }
    struct v2{
    	double x,y;
    	v2(double x=0,double y=0):x(x),y(y) {}
    	v2 operator + (const v2 &rhs) const
    		{
    			return v2(x+rhs.x,y+rhs.y);
    		}
    	v2 operator / (const double &rhs) const
    		{
    			return v2(x/rhs,y/rhs);
    		}
    	v2 operator - (const v2 &rhs) const
    		{
    			return v2(x-rhs.x,y-rhs.y);
    		}
    	double operator * (const v2 &rhs) const
    		{
    			return x*rhs.y-y*rhs.x;
    		}
    	double modulus()
    		{
    			return sqrt(x*x+y*y);
    		}
    };
    double dist(v2 a,v2 b)
    {
    	return (a-b).modulus();
    }
    v2 CirCentre(v2 a,v2 b,v2 c)
    {
    	v2 centre;
    	double a1=b.x-a.x;
    	double b1=b.y-a.y;
    	double c1=(a1*a1+b1*b1)/2.0;
    	double a2=c.x-a.x;
    	double b2=c.y-a.y;
    	double c2=(a2*a2+b2*b2)/2.0;
    	double d=a1*b2-a2*b1;
    	centre.x=a.x+(c1*b2-c2*b1)/d;
    	centre.y=a.y+(a1*c2-a2*c1)/d;
    	return centre;
    }
    bool incircle(v2 p,v2 centre,double r)
    {
    	return dcmp(dist(p,centre)-r)<=0;
    }
    void MinCircleCover(v2 *p,int n,v2 &centre,double &r)
    {
    	srand(time(NULL));
    	random_shuffle(p+1,p+1+n);
    	centre=p[1];
    	r=0;
    	for(int i=2;i<=n;++i)
    		{
    			if(!incircle(p[i],centre,r))
    				{
    					centre=p[i];
    					r=0;
    					for(int j=1;j<i;++j)
    						{
    							if(!incircle(p[j],centre,r))
    								{
    									centre=(p[i]+p[j])/2.0;
    									r=(p[i]-p[j]).modulus()/2.0;
    									for(int k=1;k<j;++k)
    										{
    											if(!incircle(p[k],centre,r))
    												{
    													centre=CirCentre(p[i],p[j],p[k]);
    													r=dist(centre,p[i]);
    												}	
    										}
    								}
    						}
    				}
    		}
    }
    int n;
    v2 p[MAXN];
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;++i)
    		scanf("%lf%lf",&p[i].x,&p[i].y);
    	v2 centre;
    	double r;
    	MinCircleCover(p,n,centre,r);
    	printf("%.3lf
    ",r);
    	return 0;
    }
    
  • 相关阅读:
    基于element-ui图片封装组件
    计算时间间隔具体每一天
    C语言学习笔记 —— 函数作为参数
    AtCoder Beginner Contest 049 题解
    AtCoder Beginner Contest 048 题解
    AtCoder Beginner Contest 047 题解
    AtCoder Beginner Contest 046 题解
    AtCoder Beginner Contest 045 题解
    AtCoder Beginner Contest 044 题解
    AtCoder Beginner Contest 043 题解
  • 原文地址:https://www.cnblogs.com/jklover/p/10388841.html
Copyright © 2011-2022 走看看