bzoj2823: [AHOI2012]信号塔&&1336: [Balkan2002]Alien最小圆覆盖&&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>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const double eps=1e-8;
double sqr(double x){return x*x;}

struct point{ double x,y;point(){} point(double X,double Y){x=X,y=Y;} };
double getdis(point p1,point p2){return sqrt(sqr(p1.x-p2.x)+sqr(p1.y-p2.y));}
point  middle(point p1,point p2){return point((p1.x+p2.x)/2,(p1.y+p2.y)/2);}
double slope (point p1,point p2)
{
    if(p2.x==p1.x)return 0;
    return (p2.y-p1.y)/(p2.x-p1.x);
}
double multi(point p1,point p2,point p0)
{
    double x1,y1,x2,y2;
    x1=p1.x-p0.x;
    y1=p1.y-p0.y;
    x2=p2.x-p0.x;
    y2=p2.y-p0.y;
    return x1*y2-x2*y1;
}

struct segment{ double k,b;segment(){} segment(double K,double B){k=K,b=B;} };
segment getseg(double k,point pp){return segment(k,pp.y-k*pp.x);}
point intersection(segment s1,segment s2)
{
    double x=(s2.b-s1.b)/(s1.k-s2.k);
    double y=s1.k*x+s1.b;
    return point(x,y);
}

//--------------------------------------simple--------------------------------------------------------

int n; point p[1100000];
bool cmp(point p1,point p2)
{
    double d=multi(p1,p2,p[1]);
    if(fabs(d)<=eps)return getdis(p1,p[1])<getdis(p2,p[1]);
    else return d>0;
}
int top,sta[1100000];
void graham()
{
    sort(p+2,p+n+1,cmp);
    top=0;sta[++top]=1,sta[++top]=2;
    double g;
    for(int i=3;i<=n;i++)
    {
        while(top>=2)
        {
            g=multi(p[sta[top]],p[i],p[sta[top-1]]);
            if(g<0||fabs(g)<=eps)top--;
            else break;
        }
        sta[++top]=i;
    }
}

//------------------------------------graham----------------------------------------------------------

point getcore(point p1,point p2,point p3)
{
    double g=multi(p1,p2,p3);
    if(fabs(g)<=eps)
    {
        double d1=getdis(p1,p2),d2=getdis(p1,p3),d3=getdis(p2,p3);
        if(d1>d2&&d1>d3)return middle(p1,p2);
        if(d2>d1&&d2>d3)return middle(p1,p3);
        if(d3>d1&&d3>d2)return middle(p2,p3);
    }
    else
    {
        segment s1,s2;
        if(slope(p1,p2)==0)
        {
            s1=getseg(-1/slope(p1,p3),middle(p1,p3));
            s2=getseg(-1/slope(p2,p3),middle(p2,p3));
        }
        else if(slope(p1,p3)==0)
        {
            s1=getseg(-1/slope(p1,p2),middle(p1,p2));
            s2=getseg(-1/slope(p2,p3),middle(p2,p3));
        }
        else
        {
            s1=getseg(-1/slope(p1,p2),middle(p1,p2));
            s2=getseg(-1/slope(p1,p3),middle(p1,p3));
        }
        return intersection(s1,s2);
    }
}

void circlecover()
{
    random_shuffle(sta+1,sta+top+1);
    point o=p[sta[1]];double r=0,d;
    for(int i=2;i<=top;i++)
        if(getdis(o,p[sta[i]])>r)
        {
            o=p[sta[i]],r=0;
            for(int j=1;j<i;j++)
                if(getdis(o,p[sta[j]])>r)
                {
                    o=middle(p[sta[i]],p[sta[j]]),r=getdis(o,p[sta[i]]);
                    for(int k=1;k<j;k++)
                        if(getdis(o,p[sta[k]])>r)
                            o=getcore(p[sta[i]],p[sta[j]],p[sta[k]]),r=getdis(o,p[sta[i]]);
                }
        }
    printf("%.2lf %.2lf %.2lf\n",o.x,o.y,r);
}

//------------------------------------solve----------------------------------------------------------

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lf%lf",&p[i].x,&p[i].y);
        if(p[i].y<p[1].y||(p[i].y==p[1].y&&p[i].x<p[1].x))
            swap(p[i],p[1]);
    }
    graham();
    circlecover();

    return 0;
}

原文地址:https://www.cnblogs.com/AKCqhzdy/p/10241525.html

时间: 2024-10-06 21:19:32

bzoj2823: [AHOI2012]信号塔&&1336: [Balkan2002]Alien最小圆覆盖&&1337: 最小圆覆盖的相关文章

BZOJ2823: [AHOI2012]信号塔

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

[日常摸鱼]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; in

【BZOJ 2823】 [AHOI2012]信号塔

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

BZOJ 2823 AHOI2012 信号塔 计算几何

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

BZOJ 1336 Balkan2002 Alien最小圆覆盖

题目大意:最小圆覆盖. 思路:再拍一份模板.做法见:http://blog.csdn.net/jiangyuze831/article/details/43950601 CODE: #define _CRT_SECURE_NO_WARNINGS #include <cmath> #include <cstdio> #include <cstring> #include <iomanip> #include <iostream> #include

BZOJ 1336 Balkan2002 Alien最小圆覆盖 随机增量法

题目大意:求最小圆覆盖 随机增量法裸题 注意多输出几位小数不然过不去= = #include <cmath> #include <cstdio> #include <cstring> #include <iomanip> #include <iostream> #include <algorithm> #define M 100100 #define EPS 1e-7 using namespace std; struct Point

P2533 [AHOI2012]信号塔

传送门 据说是一个叫做随机增量法的东西 枚举\(i\),如果不在圆中将它设为圆心 枚举\(j\),如果不在圆中将\((i,j)\)成为新的圆的直径 枚举\(k\),如果不在圆中让\(i,j,k\)组成的三角形的外接圆成为新的圆 据说在随机数据的情况下期望\(O(n)\),所以要在读进来的时候random_shuffle一下 主要是求三角形外接圆的圆心太恶心了--大概是这样的(图是偷来的) //minamoto #include<bits/stdc++.h> #define rint regis

[AHOI2012]信号塔

传送门 最小圆覆盖的板子题,和bzoj1336一样,双倍经验题 代码: #include<iostream> #include<algorithm> #include<cmath> using namespace std; void read(int &x){ char ch; bool ok; for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1; for(x=0; isdigi

bzoj2823【AHOI2012】信号塔

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