最小圆覆盖

问题:给定平面上的一个点集,求半径最小的一个圆,使得点集中的点都在其内部或上面。

随机增量算法:

  定义:点集A的最小圆覆盖是Circle(A)

  定理:如果Circle(A)=C1,且a不被C1覆盖,那么a在Circle(AU{a})的边界上。

  证明:换一种找最小圆覆盖的思路,我们初始化一些圆,圆心为A中的点,半径为0,并且让半径慢慢变大,必定存在一个时刻,所有圆的交集由空变为非空,那个最开始的非空交集是一个点,并且就是我们最小圆覆盖的圆心位置。当A中的所有点代表的圆有交集时,点a代表的圆还没有到达那个点(否则点a就被C1覆盖掉了),我们让半径继续增大,必然会有一个时刻点a代表的圆与A代表的圆的公共区域相交,这个点就是AU{a}的最小圆覆盖的圆心,它到点a的距离就是半径。

  算法:

 c = ( p[] )
for i = to n
if p[i] in c then continue
c = ( p[i] )
for j = to i-
if p[j] in c then continue
c = ( p[i], p[j] )
for k = to j-
if p[k] in c then continue
c = ( p[i], p[j], p[k] )

  ((p[i],p[j])代表包含这两个点的最小的圆)

  第一层循环的循环不变量是:c是p[1],p[2],...,p[i-1]的最小圆覆盖。

  第二层循环的循环不变量是:c是p[1],p[2],...,p[j-1]和p[i]的最小圆覆盖。

  第一层循环的循环不变量是:c是p[1],p[2],...,p[k-1],p[i]和p[j]的最小圆覆盖。

  转移用上面的定理证明。

  有个性质:上面伪代码的第10行中的三个点不可能共线(只需分别证明三个点中的一个不会在另外两个代表的线段上就行了)。

 /**************************************************************
Problem: 1336
User: idy002
Language: C++
Result: Accepted
Time:372 ms
Memory:2372 kb
****************************************************************/ #include <cstdio>
#include <cmath>
#include <algorithm>
#define line(a,b) ((b)-(a))
#define N 100010
#define eps 1e-10
using namespace std; int sg( double x ) { return (x>-eps)-(x<eps); }
struct Vector {
double x, y;
Vector(){}
Vector( double x, double y ):x(x),y(y){}
Vector operator+( const Vector &b ) const { return Vector(x+b.x,y+b.y); }
Vector operator-( const Vector &b ) const { return Vector(x-b.x,y-b.y); }
Vector operator*( double b ) const { return Vector(x*b,y*b); }
Vector operator/( double b ) const { return Vector(x/b,y/b); }
double operator^( const Vector &b ) const { return x*b.y-y*b.x; }
double len() { return sqrt(x*x+y*y); }
Vector normal() { return Vector(-y,x); }
};
typedef Vector Point;
Point inter( Point P, Vector u, Point Q, Vector v ) {
return P+u*((line(P,Q)^v)/(u^v));
}
struct Circle {
Point o;
double r;
Circle(){}
Circle( Point &a ) {
o = a;
r = ;
}
Circle( Point &a, Point &b ) {
o = (a+b)/;
r = (a-b).len()/;
}
Circle( Point &a, Point &b, Point &c ) {
Point P=(a+b)/, Q=(b+c)/;
Vector u=(a-b).normal(), v=(b-c).normal();
o = inter(P,u,Q,v);
r = (a-o).len();
}
bool contain( Point &a ) {
return sg( line(a,o).len()-r ) <= ;
}
}; int n;
Point pts[N];
Circle cir; int main() {
scanf( "%d", &n );
for( int i=; i<=n; i++ ) {
double x, y;
scanf( "%lf%lf", &x, &y );
pts[i] = Point(x,y);
}
random_shuffle( pts+, pts++n );
cir = Circle(pts[]);
for( int i=; i<=n; i++ ) {
if( cir.contain(pts[i]) ) continue;
cir = Circle(pts[i]);
for( int j=; j<i; j++ ) {
if( cir.contain(pts[j]) ) continue;
cir = Circle(pts[i],pts[j]);
for( int k=; k<j; k++ ) {
if( cir.contain(pts[k]) ) continue;
cir = Circle(pts[i],pts[j],pts[k]);
}
}
}
printf( "%.10lf\n", cir.r );
printf( "%.10lf %.10lf\n", cir.o.x, cir.o.y );
}

bzoj 1336 最小圆覆盖的更多相关文章

  1. bzoj 1337 最小圆覆盖

    /************************************************************** Problem: 1337 User: idy002 Language: ...

  2. BZOJ 1337: 最小圆覆盖1336: [Balkan2002]Alien最小圆覆盖(随机增量法)

    今天才知道有一种东西叫随机增量法就来学了= = 挺神奇的= = A.令ci为包括前i个点的最小圆,若第i+1个点无法被ci覆盖,则第i+1个点一定在ci+1上 B.令ci为包括前i个点的最小圆且p在边 ...

  3. [BZOJ 1336] [Balkan2002] Alien最小圆覆盖 【随机增量法】

    题目链接:BZOJ - 1336 题目分析 最小圆覆盖有一个算法叫做随机增量法,看起来复杂度像是 O(n^3) ,但是可以证明其实平均是 O(n) 的,至于为什么我不知道= = 为什么是随机呢?因为算 ...

  4. Bzoj 1336&1337 Alien最小圆覆盖

    1336: [Balkan2002]Alien最小圆覆盖 Time Limit: 1 Sec  Memory Limit: 162 MBSec  Special Judge Submit: 1473  ...

  5. 【BZOJ】1336: [Balkan2002]Alien最小圆覆盖

    题解 我们先把所有点random_shuffle一下 然后对前i - 1个点计算一个最小圆覆盖,然后第i个点如果不在这个圆里,那么我们把这个点当成一个新的点,作为圆心,半径为0 从头枚举1 - i - ...

  6. [BZOJ 3564] [SHOI2014] 信号增幅仪 【最小圆覆盖】

    题目链接:BZOJ - 3564 题目分析 求最小椭圆覆盖,题目给定了椭圆的长轴与 x 轴正方向的夹角,给定了椭圆长轴与短轴的比值. 那么先将所有点旋转一个角度,使椭圆长轴与 x 轴平行,再将所有点的 ...

  7. BZOJ 3564: [SHOI2014]信号增幅仪 最小圆覆盖

    3564: [SHOI2014]信号增幅仪 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=3564 Description 无线网络基站在 ...

  8. 2018.07.04 BZOJ 2823: AHOI2012信号塔(最小圆覆盖)

    2823: [AHOI2012]信号塔 Time Limit: 10 Sec Memory Limit: 128 MB Description 在野外训练中,为了确保每位参加集训的成员安全,实时的掌握 ...

  9. bzoj 2823: [AHOI2012]信号塔 最小圆覆盖

    题目大意: 给定n个点,求面积最小的园覆盖所有点.其中\(n \leq 10^6\) 题解: 恩... 刚拿到这道题的时候... 什么???最小圆覆盖不是\(O(n^3)\)的随机增量算法吗????? ...

随机推荐

  1. 洛谷 P4175: bzoj 1146: [CTSC2008]网络管理

    令人抓狂的整体二分题.根本原因还是我太菜了. 在学校写了一个下午写得头晕,回家里重写了一遍,一个小时就写完了--不过还是太慢. 题目传送门:洛谷P4175. 题意简述: 一棵 \(n\) 个结点的树, ...

  2. word文档下划线无法显示的解决方法

    在编辑文档的时候经常会遇到下划线无法显示的情况,如图: 如果遇到不能在姓名后面加下划线的情况,我们该怎么做? 请看下面的图解: 1.首先点击左上角的office图标 2.点击右下角“word选项” 3 ...

  3. Mysql转换成SqlServer数据库,以及SqlServer转换成Mysql数据库

    Windows XP sp2 MS SQL Server 2OOO sp1 MySql 5.0.41 1:MSSQLServer数据库导入到MySql数据库 步骤: 1.安装mysql数据库的ODBC ...

  4. Django-模板语言和过滤器

    Django模板语言 首先模板只是一个文本文件,它可以生成任何基于文本的格式(HTML.XML.CSS等),模板中包含变量,在模板被渲染的时候替换为最终的值,以及控制模板逻辑的标签. 变量使用{{ 变 ...

  5. mysql -> 索引_07

    索引与sql语句优化 压力测试对比

  6. 02 How to Write Go Code 如何编写go语言代码

    How to Write Go Code   如何编写go语言代码 Introduction   介绍 Code organization  组织代码 Overview  概述 Workspaces  ...

  7. 洛谷P2680运输计划

    传送门啦 要求的就是,把树上的一条边的权值设为0之后,所有路径中的最大值的最小值. 首先二分最大值,假设某次二分的最大值为x,我们首先找出所有大于x的路径(也就是我们需要通过改权缩短的路径),并把路径 ...

  8. AdvStringGrid 固定行、列

  9. Ubuntu 16.04 使用docker资料汇总与应用docker安装caffe并使用Classifier(ros kinetic+usb_cam+caffe)

    Docker是开源的应用容器引擎.若想简单了解一下,可以参考百度百科词条Docker.好像只支持64位系统. Docker官网:https://www.docker.com/ Docker - 从入门 ...

  10. pip-django-cms

    pip install django-el_pagination pip install django-ckeditor