您的位置:首页 > 其它

BZOJ 1337 最小圆覆盖 随机增量法

2015-09-11 07:28 344 查看

题意:链接

方法:随机增量法

解析:

首先把所有点打乱。

然后枚举第一个点,如果不在当前的圆内则把它设为圆心.

再枚举第二个点,如果不在当前的圆内则把圆设为其与第一个点的距离为直径的圆。

再枚举第三个点,如果不在当前的圆内则把圆设为这三个点构成三角形的外接圆。

然后最后就是答案了。

别问我这为什么是对的- -!

复杂度期望O(n),我是信了。

代码:

#include <cmath> 
#include <cstdio>
#include <iomanip> 
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 100010
using namespace std;
struct Point
{
    double x,y;
    friend istream& operator >> (istream &_,Point &a)
    {
        scanf("%lf%lf",&a.x,&a.y);
        return _;
    }
    Point(){}
    Point(double _x,double _y):x(_x),y(_y){}
    Point operator + (const Point &a)
    {return Point(x+a.x,y+a.y);} 
    Point operator - (const Point &a)
    {return Point(x-a.x,y-a.y);}
    Point operator * (double rate) 
    {return Point(x*rate,y*rate);}
    double operator * (const Point &a)
    {return x*a.x+y*a.y;}
    double operator ^ (const Point &a)
    {return x*a.y-y*a.x;}
}pt
;
struct Line
{
    Point p,v;
    Line(){}
    Line(Point a,Point b):p(a),v(b){}
};
struct Circle
{
    Point p;
    double R;
    Circle(){}
    Circle(Point _p,double _R):p(_p),R(_R){}
}ans;
double dis(Point &a,Point &b)
{
    return sqrt((a-b)*(a-b));
}
bool is_in_cir(Point &p,Circle &c)
{
    return dis(p,c.p)<=c.R;
}
Point Get_Intersection(Line &l1,Line &l2)
{
    Point u=l1.p-l2.p;
    double tmp=(l2.v^u)/(l1.v^l2.v);
    return l1.p+l1.v*tmp; 
}
Point rotate (Point a)
{
    return Point(-a.y,a.x);
}
int n;
int main()
{
    srand(19990329);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)cin>>pt[i];
    random_shuffle(pt+1,pt+n+1);
    for(int i=1;i<=n;i++)
    {
        if(!is_in_cir(pt[i],ans))
        {
            ans.p=pt[i];
            for(int j=1;j<i;j++)
            {
                if(!is_in_cir(pt[j],ans))
                {
                    ans.p=(pt[i]+pt[j])*0.5;
                    ans.R=dis(pt[i],pt[j])*0.5;
                    for(int k=1;k<j;k++)
                    {
                        if(!is_in_cir(pt[k],ans))
                        {
                            Line l1((pt[i]+pt[j])*0.5,rotate(pt[i]-pt[j]));
                            Line l2((pt[i]+pt[k])*0.5,rotate(pt[i]-pt[k]));
                            ans.p=Get_Intersection(l1,l2);
                            ans.R=dis(ans.p,pt[i]);
                        } 
                    }
                }
            }
        }
    }
    cout<<fixed<<setprecision(3)<<ans.R<<endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: