[日常摸鱼]bzoj2823 [AHOI2012]信号塔

题意:$n$个点,求最小圆覆盖,$n \leq 5e5$



这题数据是随机的hhh

我们可以先求出凸包然后对凸包上的点求最小圆覆盖…(不过直接求应该也行?)

反正随便写好像都能过…

#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cmath>
using namespace std;
const int N=500005;
struct Point
{
    double x,y;
    int rnd;
    Point(double x=0,double y=0):x(x),y(y){}
}p[N],s[N];
struct Line
{
    double k,b;
};
inline bool cmp1(Point a,Point b)
{
    if(a.x==b.x)return a.y<b.y;
    return a.x<b.x;
}
inline bool cmp2(Point a,Point b)
{
    return a.rnd<b.rnd;
}
inline Point operator +(Point a,Point b)
{
    return Point(a.x+b.x,a.y+b.y);
}
inline Point operator -(Point a,Point b)
{
    return Point(a.x-b.x,a.y-b.y);
}

inline Point operator /(Point a,double d)
{
    return Point(a.x/d,a.y/d);
}
inline double cross(Point a,Point b)
{
    return a.x*b.y-a.y*b.x;
}
inline double sqr2(double x)
{
    return x*x;
}
inline double dist(Point a,Point b)
{
    return sqrt(sqr2(a.x-b.x)+sqr2(a.y-b.y));
}
inline Line getLine(double k,Point a)
{
    Line res;res.k=k;
    res.b=a.y-a.x*k;
    return res;
}
inline Point getLineIntersection(Line l1,Line l2)
{
    Point res;
    res.x=(l2.b-l1.b)/(l1.k-l2.k);
    res.y=res.x*l1.k+l1.b;
    return res;
}
inline Point getCircle(Point a,Point b,Point c)
{
    Point p1=(a+b)/2,p2=(a+c)/2;
    double k1=-(b.x-a.x)/(b.y-a.y);
    double k2=-(c.x-a.x)/(c.y-a.y);
    Line l1=getLine(k1,p1),l2=getLine(k2,p2);
    return getLineIntersection(l1,l2);
}
inline Point minCircle(double &r,int n)
{
    for(register int i=1;i<=n;i++)s[i].rnd=rand();
    sort(s+1,s+n+1,cmp2);
    Point o=s[1];r=0;
    for(register int i=2;i<=n;i++)if(r<dist(o,s[i]))
    {
        o=s[i];r=0;
        for(register int j=1;j<i;j++)if(r<dist(o,s[j]))
        {
            o=(s[i]+s[j])/2;
            r=dist(o,s[i]);
            for(register int k=1;k<j;k++)if(r<dist(o,s[k]))
            {
                o=getCircle(s[i],s[j],s[k]);
                r=dist(o,s[i]);
            }
        }
    }
    return o;
}
inline int convexHull(int n)
{
    sort(p+1,p+n+1,cmp1);
    int t=0,k;
    for(register int i=1;i<=n;i++)
    {
        while(t>1&&cross(s[t]-s[t-1],p[i]-s[t-1])<0)t--;
        s[++t]=p[i];
    }
    k=t;
    for(register int i=n-1;i>=1;i--)
    {
        while(t>k&&cross(s[t]-s[t-1],p[i]-s[t-1])<0)t--;
        s[++t]=p[i];
    }
    if(n>1)t--;
    return t;
}
int main()
{
    int n;scanf("%d",&n);
    for(register int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
    int t=convexHull(n);double r;
    Point res=minCircle(r,t);
    printf("%.2lf %.2lf %.2lf",res.x,res.y,r);
    return 0;
}

原文地址:https://www.cnblogs.com/yoooshinow/p/8318630.html

时间: 2024-08-06 03:28:53

[日常摸鱼]bzoj2823 [AHOI2012]信号塔的相关文章

BZOJ2823: [AHOI2012]信号塔

2823: [AHOI2012]信号塔 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1097  Solved: 498[Submit][Status][Discuss] Description 在野外训练中,为了确保每位参加集训的成员安全,实时的掌握和收集周边环境和队员信息非常重要,集训队采用 的方式是在训练所在地散布N个小型传感器来收集并传递信息,这些传感器只与设在集训地中的信号塔进行通信, 信号塔接收信号的覆盖范围是圆形,可以接收到所有分布

bzoj2823: [AHOI2012]信号塔&amp;&amp;1336: [Balkan2002]Alien最小圆覆盖&amp;&amp;1337: 最小圆覆盖

首先我写了个凸包就溜了 这是最小圆覆盖问题,今晚学了一下 先随机化点,一个个加入 假设当前圆心为o,半径为r,加入的点为i 若i不在圆里面,令圆心为i,半径为0 再重新从1~i-1不停找j不在圆里面,令圆心为ij中点,直径为ij距离 再重新在1~j-1不停找k不在圆里面,三点可确定一圆,初中数学 复杂度看似O(n^3)实则O(n),好玄学 坑点:注意如果用点斜式表示方程有斜率为不存在的情况,需要特判 #include<cstdio> #include<iostream> #incl

【BZOJ 2823】 [AHOI2012]信号塔

2823: [AHOI2012]信号塔 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 469  Solved: 198 [Submit][Status][Discuss] Description 在野外训练中,为了确保每位参加集训的成员安全,实时的掌握和收集周边环境和队员信息非常重要,集训队采用的方式是在训练所在地散布N个小型传感器来收集并传递信息,这些传感器只与设在集训地中的信号塔进行通信,信号塔接收信号的覆盖范围是圆形,可以接收到所有分布在

[日常摸鱼]Uva11178Morley&#39;s Theorem-几何

题意:给一个$\Delta ABC$,分别做三个角的三等分线相交成$\Delta DEF$,求出$D,E,F$的坐标. 直接根据题意模拟 #include<cstdio> #include<cmath> #include<algorithm> using namespace std; struct Point { double x,y; Point(double x1=0,double y1=0){x=x1;y=y1;} }; typedef Point Vector;

BZOJ 2823 AHOI2012 信号塔 计算几何

题目大意:给定n个点(n<=50W),求最小圆覆盖 逗我?n<=50W?最小圆覆盖?O(n^3)? 其实数据是随机生成的 经过验证 随机生成50w的点集 平均在凸包上的点在50~60个左右 于是求凸包之后就可以随便乱搞了- - 不会写O(n^3)的最小圆覆盖 写了O(n^4)的照过 注意最小圆覆盖时要讨论有两点在圆上和有三点在圆上两种情况 --------------------以上是题解-----------以下是粗口--------------------- 出题人我*你*!!数据随机生成

[日常摸鱼]JSOI2008最大数

校运会的时候随手抽的题- 一句话题意 维护一个序列,初始为空,要求滋兹: 1.查询这个序列末尾$x$个数的最大值 2.设上一次查询的答案为$t$(如果还没查询$t=0$),在末尾插入一个数$(x+t)mod d$,$d$为给定常数 很容易想到用线段树做:记录序列的末尾,然后直接单点修改区间查询 本来想随便写完就过了的-然后一直爆零- 因为我写了一句 while(n--) 然后这题应该就没什么要注意的地方了233 贴代码 #include<cstdio> #include<cstring&

[日常摸鱼]UVA393 The Doors 简单计算几何+最短路

The  Boy Next   Doors 题意:给定一个固定大小的房间($x,y$的范围都是$[0,10]$),有$n$个墙壁作为障碍(都与横坐标轴垂直),每个墙壁都有两扇门分别用四个点来描述,起点终点固定在$(0,5)$和$(10,5)$,求起点到终点的最短路长度,$n<=18$ 题解: 我们把每堵墙的每一"段"作为一条线段,对任意两点$u,v$,如果两点间的连线不和其他线段相交,那我们从$u$走到$v$的最短距离就是他们的欧几里得距离,对所有点对都这么做一遍,处理出所有能够

[日常摸鱼]杜教筛

因为博主比较菜所以可能一些地方写的有问题或者不清楚,以及我的废话有点多- 在这里先感谢下小伙伴ww @MoebiusMeow 的帮助~ 参考资料: [1]浅谈一类积性函数的前缀和(skywalkert) [2]杜教筛--省选前的学习1(_rqy) (下面约定$[p]$表示满足条件$p$时为1不满足为0,以及下面说的函数都是数论函数) 前置技能(一些定义) 数论函数:若$f:Z^{+} \rightarrow C$,则称$f$为数论函数 积性函数:若一个数论函数$f(n)$对于所有$m_1 \bo

[日常摸鱼]字符串相关

最近开始学字符串-之前暑假听JOHNKROM大爷讲这个的时候就很懵(当时根本没碰过这个东西-) 这里大概会有一些相关的算法和自己做的题,还有存一些模板啥的. 由于我太弱了所以可能不会写有关原理的东西(或者等我哪天会了有空再补)如果是刚学的话还是去网上找教程吧-我就存个题还有模板啥的orz Trie字典树(Trie),根节点为空节点,其他节点(或边上)放字母,然后节点上还能储存一些其他信息. 1.一个类似模板题的东西:luogu2580 建一颗Trie,把所有名字插进去,结束的地方打个标记,具体见