BZOJ

洛谷


一个经典的随机增量法,具体可以看这里,只记一下大体流程。

一个定理:如果一个点\(p\)不在点集\(S\)的最小覆盖圆内,那么它一定在\(S\bigcup p\)的最小覆盖圆上。

所以假设我们有了前\(i-1\)个点的最小覆盖圆,那么只需要判断\(i\)在不在其内,就可以确定\(i\)是否在当前最小覆盖圆上。

算法流程:

  1. 设前\(i-1\)个点的最小覆盖圆是\(C\),判断第\(i\)个点是否在\(C\)内。如果是,则\(i\)个点的最小覆盖圆也是\(C\);否则进行\(2\)。
  2. 确定\(p_i\)为最小覆盖圆上的一个点。枚举点\(j\),判断\(j\)是否在当前最小覆盖圆内。如果是,跳过;否则确定\(p_j\)也是最小覆盖圆上的一个点,圆心为线段\((p_i,p_j)\)的中点,半径为\(\frac{dis(p_i,p_j)}{2}\),进行\(3\)。
  3. 枚举点\(k\),判断\(k\)是否在当前最小覆盖圆内。如果是,跳过;否则确定当前最小覆盖圆为\((p_i,p_j,p_k)\)的外接圆。

算法的复杂度分析:(随机数据下,)因为只需要确定三个点,\(n\)个点中每个点在圆上的概率是\(\frac3n\)。

那么第一层循环的复杂度\(T_1(n)=O(n)+\sum_{i=1}^nT_2(i)\),第二层循环复杂度\(T_2(n)=O(n)+\sum_{i=1}^nT_3(i)\),第三次循环复杂度为\(T_3(n)=O(n)\)。

化简一下就可以得出算法的均摊复杂度为\(O(n)\)。

注意要保证点的顺序是随机的。

具体细节:

如何求三个点\((p_i,p_j,p_k)\)的最小覆盖圆:

就是用一个性质。。垂直平分线(中垂线)上的点到线段两边点的距离相同。那么求出两条线段的垂直平分线,求个交点就行了。

垂直平分线的求法就是先求一个中点(坐标相加除以\(2\)),然后做垂线(将另一个两点之间的向量旋转\(90^{\circ}\))。


//16952kb	780ms
#include <cmath>
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define MAXIN 500000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=1e6+5; char IN[MAXIN],*SS=IN,*TT=IN;
struct Vec
{
double x,y;
Vec(double x=0,double y=0):x(x),y(y) {}
Vec operator +(const Vec &a)const {return Vec(x+a.x, y+a.y);}
Vec operator -(const Vec &a)const {return Vec(x-a.x, y-a.y);}
Vec operator *(const double a)const {return Vec(x*a, y*a);}
double operator *(const Vec &a)const {return x*a.y-y*a.x;}
Vec Rotate_90()const {return Vec(y,-x);}
double len()const {return sqrt(x*x+y*y);}
double len2()const {return x*x+y*y;}
}p[N];
typedef Vec Point;
struct Line
{
Point p; Vec v;
Line(Point p,Vec v):p(p),v(v) {}
Line PerpendicularBisector()const//垂直平分线=-=
{
return Line((p+p+v)*0.5,v.Rotate_90());
}
Point Intersection(const Line &l)const
{
return p+v*((l.v*(p-l.p))/(v*l.v));
}
}; inline double read()
{
double x=0,y=0.1,f=1;register char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);x=x*10+c-48,c=gc());
for(c=='.'&&(c=gc());isdigit(c);x+=y*(c-48),y*=0.1,c=gc());
return x*f;
}
Point CalcCircle(const Point &a,const Point &b,const Point &c)
{
// Line A=Line(a,b-a).PerpendicularBisector(),B=Line(a,c-a).PerpendicularBisector();
Line A=Line((a+b)*0.5,(b-a).Rotate_90()),B=Line((a+c)*0.5,(c-a).Rotate_90());
return A.Intersection(B);
}
void Solve(const int n)
{
srand(330), std::random_shuffle(p+1,p+1+n);//话说这个srand不够随机啊= =
Point O=p[1]; double R=0;
for(int i=2; i<=n; ++i)
if((p[i]-O).len2()>R)
{
O=p[i], R=0;
for(int j=1; j<i; ++j)
if((p[j]-O).len2()>R)
{
O=(p[i]+p[j])*0.5, R=(p[i]-O).len2();
for(int k=1; k<j; ++k)
if((p[k]-O).len2()>R)
O=CalcCircle(p[i],p[j],p[k]), R=(p[k]-O).len2();
}
}
printf("%.2f %.2f %.2f\n",O.x,O.y,sqrt(R));
} int main()
{
int n=read();
for(int i=1; i<=n; ++i) p[i].x=read(),p[i].y=read();
// for(int i=1; i<=n; ++i) p[i]=(Point){read(),read()};//声明构造函数之后再这么用,貌似。。= = 不同编译器结果不同。。
Solve(n); return 0;
}

BZOJ.2823.[AHOI2012]信号塔(最小圆覆盖 随机增量法)的更多相关文章

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

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

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

    题目描述 给出N个点,让你画一个最小的包含所有点的圆. 输入 先给出点的个数N,2<=N<=100000,再给出坐标Xi,Yi.(-10000.0<=xi,yi<=10000. ...

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

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

  4. BZOJ 2823: [AHOI2012]信号塔

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2823 随机增量法.不断加点维护圆,主要是三点共圆那里打得烦(其实也就是个两中垂线求交点+联立方 ...

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

    [BZOJ1336][Balkan2002]Alien最小圆覆盖 Description 给出N个点,让你画一个最小的包含所有点的圆. Input 先给出点的个数N,2<=N<=10000 ...

  6. AHOI2012 信号塔 | 最小圆覆盖模板

    题目链接:戳我 最小圆覆盖. 1.枚举第一个点,考虑当前圆是否包含了这个点,如果没有,则把圆变成以这个点为圆心,半径为0的圆. 2.枚举第二个点,考虑圆是否包含了这个点,如果没有,则把圆变成以这两个点 ...

  7. [BZOJ2823][BZOJ1336][BZOJ1337]最小圆覆盖(随机增量法)

    算法介绍网上有很多,不解释了. 给出三点坐标求圆心方法:https://blog.csdn.net/liyuanbhu/article/details/52891868 记得先random_shuff ...

  8. hdu 3007【最小圆覆盖-随机增量法模板】

    #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> usin ...

  9. 【BZOJ】2823: [AHOI2012]信号塔

    题意 给\(n\)个点,求一个能覆盖所有点的面积最小的圆.(\(n \le 50000\)) 分析 随机增量法 题解 理论上\(O(n^3)\)暴力,实际上加上随机化后期望是\(O(n)\)的. 算法 ...

随机推荐

  1. OSU! on tree

    dsu on tree 好吧,这个毒瘤...... 树剖和启发式合并的杂合体. 用于解决静态子树问题,复杂度O(nlogn * insert时间) 因为dsu是并查集的意思所以算法名字大概就是什么树上 ...

  2. Pandas系列(二)- DataFrame数据框

    一.初识DataFrame dataFrame 是一个带有索引的二维数据结构,每列可以有自己的名字,并且可以有不同的数据类型.你可以把它想象成一个 excel 表格或者数据库中的一张表DataFram ...

  3. 常见Web攻击

    一.SQL注入 1. sql注入的危害 非法读取.篡改.删除数据库中的数据 盗取用户的各类敏感信息,获取利益 通过修改数据库来修改网页上的内容 注入木马等 2. 实例 MYSQLDB # 通过在用户名 ...

  4. openstack项目【day23】:keystone组件基础

    本节内容 一 什么是keystone 二 为何要有keystone 三 keystone的功能 四 keystone概念详解 五 keystone内包含的组件 六 keystone与openstack ...

  5. solr的域

    solrhom相当于存放数据的地方,里面一个个文件相当于数据库,每个数据库里面有两个文件夹,一个data,一个conf,conf下有一个schema.xml文件,配置域,相当于表的字段. solr中内 ...

  6. [Android] Android 锁屏实现与总结 (三)

    上接: Android 锁屏实现与总结 (二) 系列文章链接如下: [Android] Android 锁屏实现与总结 (一) [Android] Android 锁屏实现与总结 (二) [Andro ...

  7. C# 处理文件的压缩与解压

    最近做了一个关于winform 程序更新下载的功能,大概思路是,程序检测到服务端系统版本号发生改变,系统需要更新:这时请求服务端更新地址,下载更新包到程序的根目录,更新包是一个压缩包,下载完后再把压缩 ...

  8. Django之会议室预预订

    model表设计: from django.db import models from django.contrib.auth.models import AbstractUser # Create ...

  9. JQuery EasyUI 初始

    基于jQuery的用户界面插件集合 1. jQuery easyui提供了一个完整的组件的集合,包括强大的DataGrid,树网格,面板.用户可以使用他们一起,或者只是用一些组件,组合和构建他想要的跨 ...

  10. TCP-IP详解笔记6

    TCP-IP详解笔记6 用户数据报协议和IP分片 UDP是一种保留消息边界的面向数据报的传输层协议. 不提供差错纠正, 队列管理, 重复消除, 流量控制和拥塞控制. 提供差错检测, 端到端(end-t ...