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

题意:链接

方法:随机增量法

解析:

首先把所有点打乱。

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

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

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

然后最后就是答案了。

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

复杂度期望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[N];
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;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-13 17:12:22

BZOJ 1337 最小圆覆盖 随机增量法的相关文章

BZOJ 1336 Balkan2002 Alien最小圆覆盖 随机增量法

题目大意:求最小圆覆盖 随机增量法裸题 注意多输出几位小数不然过不去= = #include <cmath> #include <cstdio> #include <cstring> #include <iomanip> #include <iostream> #include <algorithm> #define M 100100 #define EPS 1e-7 using namespace std; struct Point

【bzoj1336/1337/2823】[Balkan2002]Alien最小圆覆盖 随机增量法

题目描述 给出N个点,让你画一个最小的包含所有点的圆. 输入 先给出点的个数N,2<=N<=100000,再给出坐标Xi,Yi.(-10000.0<=xi,yi<=10000.0) 输出 输出圆的半径,及圆心的坐标 样例输入 6 8.0 9.0 4.0 7.5 1.0 2.0 5.1 8.7 9.0 2.0 4.5 1.0 样例输出 5.00 5.00 5.00 题解 随机增量法求最小圆覆盖裸题 求法:设初始圆为某空圆,先枚举第一个点,如果不在当前圆内,则令当前圆为这一个点的最小圆

【BZOJ1336】[Balkan2002]Alien最小圆覆盖 随机增量法

[BZOJ1336][Balkan2002]Alien最小圆覆盖 Description 给出N个点,让你画一个最小的包含所有点的圆. Input 先给出点的个数N,2<=N<=100000,再给出坐标Xi,Yi.(-10000.0<=xi,yi<=10000.0) Output 输出圆的半径,及圆心的坐标 Sample Input 6 8.0 9.0 4.0 7.5 1.0 2.0 5.1 8.7 9.0 2.0 4.5 1.0 Sample Output 5.00 5.00 5

hdu 3007【最小圆覆盖-随机增量法】

#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int N=505; int n; double r; struct dian { double x,y; dian(double X=0,double Y=0) { x=X,y=Y; } dian operator + (const dian &a) c

bzoj 1337 最小圆覆盖

bzoj 1337 最小圆覆盖 补充一个求三角形外心的向量法.用了点积的几何意义,很实用.出处. 使用随机增量法求.首先随机打乱顺序,然后三重循环,选择当前在圆外的点更新圆,分别按照 \(1/2/3\) 个点确定圆的方式更新即可. 由于随机一个点不在前 \(i\) 个点的最小覆盖圆内的概率是 \(\frac 3 i\) ,可以证明这样的时间复杂度是 \(O(n)\) 的,这种做法可以推广到常数维度上,时间复杂度仍为 \(O(n)\) . #include<bits/stdc++.h> usin

【BZOJ-1336&amp;1337】Alie最小圆覆盖 最小圆覆盖(随机增量法)

1336: [Balkan2002]Alien最小圆覆盖 Time Limit: 1 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 1573  Solved: 697[Submit][Status][Discuss] Description 给出N个点,让你画一个最小的包含所有点的圆. Input 先给出点的个数N,2<=N<=100000,再给出坐标Xi,Yi.(-10000.0<=xi,yi<=10000.0) Outpu

BZOJ 2280 Poi2011 Plot 二分答案+随机增量法

题目大意:给定n个点,要求分成m段,使每段最小覆盖圆半径的最大值最小 二分答案,然后验证的时候把点一个个塞进最小覆盖圆中,若半径超了就分成一块-- 等等你在跟我说不随机化的随机增量法? 好吧 那么对于一个点pos,我们要计算最大的bound满足[pos,bound]区间内的最小覆盖圆半径不超过二分的值 直接上二分是不可取的,因为我们要求m次,如果每次都验证一遍[1,n/2]直接就炸了 我们可以这么搞 首先判断[pos,pos+1-1]是否满足要求 然后判断[pos,pos+2-1]是否满足要求

bzoj2823: [AHOI2012]信号塔&amp;&amp;1336: [Balkan2002]Alien最小圆覆盖&amp;&amp;1337: 最小圆覆盖

首先我写了个凸包就溜了 这是最小圆覆盖问题,今晚学了一下 先随机化点,一个个加入 假设当前圆心为o,半径为r,加入的点为i 若i不在圆里面,令圆心为i,半径为0 再重新从1~i-1不停找j不在圆里面,令圆心为ij中点,直径为ij距离 再重新在1~j-1不停找k不在圆里面,三点可确定一圆,初中数学 复杂度看似O(n^3)实则O(n),好玄学 坑点:注意如果用点斜式表示方程有斜率为不存在的情况,需要特判 #include<cstdio> #include<iostream> #incl

Bzoj 1336&amp;1337 Alien最小圆覆盖

1336: [Balkan2002]Alien最小圆覆盖 Time Limit: 1 Sec  Memory Limit: 162 MBSec  Special Judge Submit: 1473  Solved: 648 [Submit][Status][Discuss] Description Input 先给出点的个数N,2<=N<=100000,再给出坐标Xi,Yi.(-10000.0<=xi,yi<=10000.0) Output Sample Input 6 8.0