BZOJ.2823.[AHOI2012]信号塔(最小圆覆盖 随机增量法)
一个经典的随机增量法,具体可以看这里,只记一下大体流程。
一个定理:如果一个点\(p\)不在点集\(S\)的最小覆盖圆内,那么它一定在\(S\bigcup p\)的最小覆盖圆上。
所以假设我们有了前\(i-1\)个点的最小覆盖圆,那么只需要判断\(i\)在不在其内,就可以确定\(i\)是否在当前最小覆盖圆上。
算法流程:
- 设前\(i-1\)个点的最小覆盖圆是\(C\),判断第\(i\)个点是否在\(C\)内。如果是,则\(i\)个点的最小覆盖圆也是\(C\);否则进行\(2\)。
- 确定\(p_i\)为最小覆盖圆上的一个点。枚举点\(j\),判断\(j\)是否在当前最小覆盖圆内。如果是,跳过;否则确定\(p_j\)也是最小覆盖圆上的一个点,圆心为线段\((p_i,p_j)\)的中点,半径为\(\frac{dis(p_i,p_j)}{2}\),进行\(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]信号塔(最小圆覆盖 随机增量法)的更多相关文章
- bzoj 2823: [AHOI2012]信号塔 最小圆覆盖
题目大意: 给定n个点,求面积最小的园覆盖所有点.其中\(n \leq 10^6\) 题解: 恩... 刚拿到这道题的时候... 什么???最小圆覆盖不是\(O(n^3)\)的随机增量算法吗????? ...
- 【bzoj1336/1337/2823】[Balkan2002]Alien最小圆覆盖 随机增量法
题目描述 给出N个点,让你画一个最小的包含所有点的圆. 输入 先给出点的个数N,2<=N<=100000,再给出坐标Xi,Yi.(-10000.0<=xi,yi<=10000. ...
- 2018.07.04 BZOJ 2823: AHOI2012信号塔(最小圆覆盖)
2823: [AHOI2012]信号塔 Time Limit: 10 Sec Memory Limit: 128 MB Description 在野外训练中,为了确保每位参加集训的成员安全,实时的掌握 ...
- BZOJ 2823: [AHOI2012]信号塔
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2823 随机增量法.不断加点维护圆,主要是三点共圆那里打得烦(其实也就是个两中垂线求交点+联立方 ...
- 【BZOJ1336】[Balkan2002]Alien最小圆覆盖 随机增量法
[BZOJ1336][Balkan2002]Alien最小圆覆盖 Description 给出N个点,让你画一个最小的包含所有点的圆. Input 先给出点的个数N,2<=N<=10000 ...
- AHOI2012 信号塔 | 最小圆覆盖模板
题目链接:戳我 最小圆覆盖. 1.枚举第一个点,考虑当前圆是否包含了这个点,如果没有,则把圆变成以这个点为圆心,半径为0的圆. 2.枚举第二个点,考虑圆是否包含了这个点,如果没有,则把圆变成以这两个点 ...
- [BZOJ2823][BZOJ1336][BZOJ1337]最小圆覆盖(随机增量法)
算法介绍网上有很多,不解释了. 给出三点坐标求圆心方法:https://blog.csdn.net/liyuanbhu/article/details/52891868 记得先random_shuff ...
- hdu 3007【最小圆覆盖-随机增量法模板】
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> usin ...
- 【BZOJ】2823: [AHOI2012]信号塔
题意 给\(n\)个点,求一个能覆盖所有点的面积最小的圆.(\(n \le 50000\)) 分析 随机增量法 题解 理论上\(O(n^3)\)暴力,实际上加上随机化后期望是\(O(n)\)的. 算法 ...
随机推荐
- OSU! on tree
dsu on tree 好吧,这个毒瘤...... 树剖和启发式合并的杂合体. 用于解决静态子树问题,复杂度O(nlogn * insert时间) 因为dsu是并查集的意思所以算法名字大概就是什么树上 ...
- Pandas系列(二)- DataFrame数据框
一.初识DataFrame dataFrame 是一个带有索引的二维数据结构,每列可以有自己的名字,并且可以有不同的数据类型.你可以把它想象成一个 excel 表格或者数据库中的一张表DataFram ...
- 常见Web攻击
一.SQL注入 1. sql注入的危害 非法读取.篡改.删除数据库中的数据 盗取用户的各类敏感信息,获取利益 通过修改数据库来修改网页上的内容 注入木马等 2. 实例 MYSQLDB # 通过在用户名 ...
- openstack项目【day23】:keystone组件基础
本节内容 一 什么是keystone 二 为何要有keystone 三 keystone的功能 四 keystone概念详解 五 keystone内包含的组件 六 keystone与openstack ...
- solr的域
solrhom相当于存放数据的地方,里面一个个文件相当于数据库,每个数据库里面有两个文件夹,一个data,一个conf,conf下有一个schema.xml文件,配置域,相当于表的字段. solr中内 ...
- [Android] Android 锁屏实现与总结 (三)
上接: Android 锁屏实现与总结 (二) 系列文章链接如下: [Android] Android 锁屏实现与总结 (一) [Android] Android 锁屏实现与总结 (二) [Andro ...
- C# 处理文件的压缩与解压
最近做了一个关于winform 程序更新下载的功能,大概思路是,程序检测到服务端系统版本号发生改变,系统需要更新:这时请求服务端更新地址,下载更新包到程序的根目录,更新包是一个压缩包,下载完后再把压缩 ...
- Django之会议室预预订
model表设计: from django.db import models from django.contrib.auth.models import AbstractUser # Create ...
- JQuery EasyUI 初始
基于jQuery的用户界面插件集合 1. jQuery easyui提供了一个完整的组件的集合,包括强大的DataGrid,树网格,面板.用户可以使用他们一起,或者只是用一些组件,组合和构建他想要的跨 ...
- TCP-IP详解笔记6
TCP-IP详解笔记6 用户数据报协议和IP分片 UDP是一种保留消息边界的面向数据报的传输层协议. 不提供差错纠正, 队列管理, 重复消除, 流量控制和拥塞控制. 提供差错检测, 端到端(end-t ...