题面

传送门

前置芝士

最小圆覆盖

题解

我们按照\(x\)坐标排序,然后二分中间点,把点分成左右两边,对两边都做一个最小圆覆盖,那么半径大一点的那个就是答案了。然后对半径大的那一边继续二分就行了

然而这里显然会有一个问题……就是如果最优解中把点分成两个点集的那条直线是斜的该怎么办……

那么我们就把整个坐标系转一下好了……枚举一下偏角,然后把所有点逆时针转过这个角度……实测大概每次转\({2\pi \over 100}\),转\(100\)次差不多就可以了

还有一个我很好奇的问题,如果有三点共线的情况,那么最小圆覆盖求两条中垂线交点的时候可能会出现中垂线平行的情况显然是会\(gg\)的,所以解决办法要么是特判平行要么是加上微小扰动来避免三点共线,然而我看了看别人的似乎都没管这一点也能\(A\)……

哪位鸽鸽能告诉我这是为什么么qwq

//minamoto
#include<bits/stdc++.h>
#define R register
#define inline __inline__ __attribute__((always_inline))
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
double readdb()
{
R double x=0,y=0.1,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(x=ch-'0';(ch=getc())>='0'&&ch<='9';x=x*10+ch-'0');
for(ch=='.'&&(ch=getc());ch>='0'&&ch<='9';x+=(ch-'0')*y,y*=0.1,ch=getc());
return x*f;
}
const int N=1005;const double an=1.0/100*acos(-1.0),eps=1e-9;
const double si=sin(an),co=cos(an);
inline int sgn(R double x){return x<-eps?-1:x>eps;}
inline double reps(){return (1.0*rand()/RAND_MAX-0.5)*eps;}
struct node{
double x,y;
inline node(){}
inline node(R double xx,R double yy):x(xx),y(yy){}
inline node operator +(const node &b)const{return node(x+b.x,y+b.y);}
inline node operator -(const node &b)const{return node(x-b.x,y-b.y);}
inline double operator *(const node &b)const{return x*b.y-y*b.x;}
inline node operator *(const double &b)const{return node(x*b,y*b);}
inline double operator ^(const node &b)const{return x*b.x+y*b.y;}
inline double len2(){return x*x+y*y;}
inline node rot(){return node(x*co-y*si,x*si+y*co);}
inline node rot90(){return node(-y,x);}
inline void shake(){x+=reps(),y+=reps();}
}p[N],st[N],o;
inline bool cmp(const node &a,const node &b){return a.x<b.x;}
struct Line{
node p,v;
inline Line(){}
inline Line(R node pp,R node vv):p(pp),v(vv){}
friend node cross(const Line &a,const Line &b){return a.p+a.v*(b.v*(b.p-a.p)/(b.v*a.v));}
};
node circle(R node a,R node b,R node c){
return cross(Line((a+b)*0.5,(b-a).rot90()),Line((a+c)*0.5,(c-a).rot90()));
}
double query(int l1,int l2){
if(l1>l2)return 0;
int top=0;double r=0;o=node(0,0);
fp(i,l1,l2)st[++top]=p[i];
random_shuffle(st+1,st+1+top);
fp(i,1,top)if(sgn((st[i]-o).len2()-r)>0){
o=st[i],r=0;
fp(j,1,i-1)if(sgn((st[j]-o).len2()-r)>0){
o=(st[i]+st[j])*0.5,r=(st[i]-o).len2();
fp(k,1,j-1)if(sgn((st[k]-o).len2()-r)>0)
o=circle(st[i],st[j],st[k]),r=(st[i]-o).len2();
}
}
return r;
}
int n;double res;
int main(){
srand(20030719);
// freopen("testdata.in","r",stdin);
while(n=read()){
fp(i,1,n)p[i].x=readdb(),p[i].y=readdb(),p[i].shake();
res=1e18;
fp(d,1,160){
fp(i,1,n)p[i]=p[i].rot();
sort(p+1,p+1+n,cmp);
int l=1,r=n;
while(l<=r){
int mid=(l+r)>>1;
double r1=query(1,mid),r2=query(mid+1,n);
double ans=r1<r2?r2:r1;
if(r1+r2-ans>res)break;
cmin(res,ans);
r1<r2?l=mid+1:r=mid-1;
}
}
printf("%.2lf\n",sqrt(res));
}
return 0;
}

洛谷P4586 [FJOI2015]最小覆盖双圆问题(最小圆覆盖)的更多相关文章

  1. 洛谷 P4585 [FJOI2015]火星商店问题 解题报告

    P4585 [FJOI2015]火星商店问题 题目描述 火星上的一条商业街里按照商店的编号\(1,2,\dots,n\) ,依次排列着\(n\)个商店.商店里出售的琳琅满目的商品中,每种商品都用一个非 ...

  2. 洛谷 P4585 [FJOI2015]火星商店问题

    (勿看,仅作笔记) bzoj权限题... https://www.luogu.org/problemnew/show/P4585 对于特殊商品,直接可持久化trie处理一下即可 剩下的,想了一段时间c ...

  3. 洛谷$P4585\ [FJOI2015]$火星商店问题 线段树+$trie$树

    正解:线段树+$trie$树 解题报告: 传送门$QwQ$ $umm$题目有点儿长我先写下题目大意趴$QwQ$,就说有$n$个初始均为空的集合和$m$次操作,每次操作为向某个集合内加入一个数$x$,或 ...

  4. [洛谷P4585] [FJOI2015] 火星商店问题

    Description 火星上的一条商业街里按照商店的编号 \(1\),\(2\) ,-,\(n\) ,依次排列着 \(n\) 个商店.商店里出售的琳琅满目的商品中,每种商品都用一个非负整数 \(va ...

  5. 【洛谷】P4585 [FJOI2015]火星商店问题

    题解 题目太丧,OJ太没有良心,我永远喜欢LOJ! (TLE报成RE,垃圾洛谷,我永远喜欢LOJ) 好的,平复一下我debug了一上午崩溃的心态= =,写一写这道题的题解 把所有限制去掉,给出一个值, ...

  6. (bzoj1337 || 洛谷P1742 最小圆覆盖 )|| (bzoj2823 || 洛谷P2533 [AHOI2012]信号塔)

    bzoj1337 洛谷P1742 用随机增量法.讲解:https://blog.csdn.net/jokerwyt/article/details/79221345 设点集A的最小覆盖圆为g(A) 可 ...

  7. 洛谷 P2279 [HNOI2003]消防局的设立 (树形dp or 贪心)

    一看到这道题就知道是树形dp 之前做过类似的题,只不过保护的范围是1 所以简单很多. 这道题保护的范围是2,就复杂了很多. 我就开始列状态,然后发现竟然有5种 然后我就开始列方程. 但是我考虑的时候是 ...

  8. 洛谷 P1514 【引水入城】

    题库 :洛谷 题号 :1514 题目 :引水入城 link :https://www.luogu.org/problemnew/show/P1514 思路 :搜索从第一排开始能覆盖最后一排的区间L ~ ...

  9. 洛谷1640 bzoj1854游戏 匈牙利就是又短又快

    bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...

随机推荐

  1. VS Code 界面语言设置

    首先Ctrl+shift+p打开命令面板. 输入配置显示语言 回车 更改locale即可更改页面显语言(更改后需重启软件). 目前支持如下语言 Display Language Locale Engl ...

  2. docker-compose搭建单机多节点es + kibana

    docker-compose.yml配置如下: version: '2.2' services: elasticsearch: image: docker.elastic.co/elasticsear ...

  3. Java常用的输出调试技巧

    --------siwuxie095                 Eclipse 开发中常用的输出调试技巧:     先在左侧的 Package Explorer,右键->New->J ...

  4. 链表求和12 · Add Two Numbers

    反向存储,从左往右加 [抄题]: 你有两个用链表代表的整数,其中每个节点包含一个数字.数字存储按照在原来整数中相反的顺序,使得第一个数字位于链表的开头.写出一个函数将两个整数相加,用链表形式返回和.给 ...

  5. rabbitmq的延迟消息队列实现

    第一部分:延迟消息的实现原理和知识点 使用RabbitMQ来实现延迟任务必须先了解RabbitMQ的两个概念:消息的TTL和死信Exchange,通过这两者的组合来实现上述需求. 消息的TTL(Tim ...

  6. iis 搭建ftp

    1.打开iis,添加FTP站点 2.在电脑上建立的FTP服务器别的电脑不能访问 关闭防火墙即可访问防火墙 程序员的基础教程:菜鸟程序员

  7. CHANGE DETECTION IN ANGULAR 2

    In this article I will talk in depth about the Angular 2 change detection system. HIGH-LEVEL OVERVIE ...

  8. jdbc注册驱动 class.forName()

    从源码 D:\Javasoftware\MySql\mysql\mysql-connector-java-5.1.7\src\com\mysql\jdbc\Driver.java class.forN ...

  9. KbmMW 4.40.00 测试发布

    经过漫长的等待,支持移动开发的kbmmw 4.40.00 终于发布了,这次不但支持各个平台的开发, 而且增加了认证管理器等很多新特性,非常值得升级.具体见下表. 4.40.00 BETA 1 Oct ...

  10. android 播放视频时切换全屏隐藏状态栏

    1. Demo: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstance ...