最小圆覆盖(Smallest Enclosing Discs)

随机增量算法(a randomized incremental algorithm)

#define sqr(x) ((x)*(x))
#define EPS 1e-4

struct P{
    double x, y;
    P(double x, double y):x(x),y(y){}
    P(P &a, P &b):x(b.x-a.x),y(b.y-a.y){}
    P(){}
    P mid(P &a){
        return P((a.x+x)/2, (a.y+y)/2);
    }
    double cross(P &a){
        return x*a.y-y*a.x;
    }
    double len2(){
        return sqr(x)+sqr(y);
    }
    double dis(P &a){
        return sqrt(sqr(x-a.x)+sqr(y-a.y));
    }
    void print(){
        printf("%f %f\n", x, y);
    }
};

struct Disc{
    P o;
    double r;
    bool cover(P &a){
        return r-o.dis(a) >= -EPS;
    }
    Disc(){}
    Disc(P &o, double r):o(o),r(r){}
    Disc(P &a, P &b):o(a.mid(b)), r(a.dis(b)/2){}
    Disc(P &a, P &b, P &c){
        double t1=b.len2()-a.len2();
        double t2=c.len2()-a.len2();
        P p1(a, b), p2(a, c);
        double t3=p1.cross(p2)*2;
        P p3(t1, p1.y), p4(t2, p2.y);
        P p5(p1.x, t1), p6(p2.x, t2);
        o=P(p3.cross(p4)/t3, p5.cross(p6)/t3);
        r=o.dis(a);
    }
};

Disc MinDisc(vector<P> &p){
    if(p.size()<=1) return Disc();
    random_shuffle(p.begin(), p.end());
    Disc d(p[0], p[1]);
    for(int i=2; i<p.size(); i++)
        if(!d.cover(p[i])){
            d=Disc(p[0], p[i]);
            for(int j=1; j<i; j++)
                if(!d.cover(p[j])){
                    d=Disc(p[i], p[j]);
                    for(int k=0; k<j; k++)
                        if(!d.cover(p[k]))
                            d=Disc(p[i], p[j], p[k]);
                }
        }
    return d;
}
时间: 2024-12-22 22:56:36

最小圆覆盖(Smallest Enclosing Discs)的相关文章

HDOJ 3007 Buried memory 增量法最小圆覆盖

增量法最小圆覆盖,简单模版 Buried memory Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2541    Accepted Submission(s): 1365 Problem Description Each person had do something foolish along with his or her g

【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

BZOJ1337: 最小圆覆盖

题目:求n个点的最小圆覆盖. 题解:最小圆覆盖,上模板.复杂度证明可以戳:这里 代码: 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<iostream> 7 #include<vector> 8 #include<map> 9 #inclu

最小圆覆盖模板

//最小圆覆盖 //输入: 从下标0开始的点集_ps和大小_n //输出: 覆盖所有点的最小圆 //复杂度: O(n) //注意: 会对_ps进行随机处理操作,将会改变点集的内部顺序 Circle MinCoverCir(Point _ps[],int _n) { //随机处理,但是会改变传入的点集. random_shuffle(_ps, _ps+_n);//复杂度O(_n) Circle rec; rec.r = 0; rec.c = _ps[0]; for(int i=1;i<_n;i++

ZOJ 1450 Minimal Circle 最小圆覆盖

套了个模板直接上,貌似没有随机化序列 QAQ //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #include <cstring> #include <cmath> #include <stack> #include <queue> #include <

最小圆覆盖 hdu 3007

今天学习了一下最小圆覆盖, 看了一下午都没看懂, 晚上慢慢的摸索这代码,接合着别人的讲解, 画着图跟着代码一步一步的走着,竟然有些理解了. 最小圆覆盖: 给定n个点, 求出半径最小的圆可以把这些点全部包围, 可以在圆的边界上 下面是我的个人理解. 如果不对, 还请路过大牛指出 先找一个点, 让圆心等于这个点的坐标, 半径等于0, 显然这个对的, 接着找下一个点, 如果只有两个点的话, 那么最小的圆一定是以他们为直径做圆, 接着找第三个点, 如果第三个点在园内或者在边界上, 那么不用更新当前的最小

BZOJ 2823 AHOI 2012 信号塔 凸包+最小圆覆盖

题目大意:给出平面上n个点,求最小圆覆盖. 思路:圆覆盖问题只与所有点中凸包上的点有关,因此先求一下凸包,然后数据范围骤减.大概是只剩下logn左右个点.这样就可以随便浪了. 先找所有三个点组成的圆,然后找两个点为直径所组成的圆. 还有就是三角形的外心公式,简直不是人推的,然后我就机制的百度了,结果如下: 不要模拟退火... 样例很坑,当你算出2.49 2.86的时候,不要认为你被卡精了,其实是你写挂了... CODE: #include <cmath> #include <cstdio

【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 题解 随机增量法求最小圆覆盖裸题 求法:设初始圆为某空圆,先枚举第一个点,如果不在当前圆内,则令当前圆为这一个点的最小圆

最小圆覆盖

本来不想学的-于是今天就碰到一道大裸题- 例题:bzoj2823 求最小圆覆盖n个点. 伪代码如下: 把所有点随机化,设为(x[1],y[1])...(x[n],y[n]) 开始把圆心设为x[1],半径设为0 for i=2 to n 如果i号点在当前圆内则跳过 //那么i号点就在圆周上 把1号点和i号点作为直径作一个圆 for j=1 to i-1 如果j号点在当前圆内则跳过 考虑以j号点和i号点作为直径作一个圆 for k=1 to j-1 如果k号点在当前圆内则跳过 以i,j,k三点组成的