您的位置:首页 > 其它

【BZOJ2823】【AHOI2012】信号塔 最小圆覆盖 计算几何

2015-06-23 14:04 465 查看

链接:

#include <stdio.h>
int main()
{
    puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢");
    puts("网址:blog.csdn.net/vmurder/article/details/46605193");
}


题解之前:

首先最小圆覆盖虽然有三层 forfor 循环,但是它是期望 O(n)O(n) 的。什么?你问我为啥?那我只能呵呵了,50W的 O(n3)O(n^3) 高速跑过。




后交的是不求凸包直接跑的,先交的是求了凸包再跑的。。并没有什么差距。

题解:

这道题我们可以先写一份求凸包来缩减点的规模,如果点是随机生成的,那么期望有不到100个点在凸包上,然后就可以乱搞了(其实毛用没有2333)

然后这道题需要用到 [最小圆覆盖] (呃其实这道题就是裸的最小圆覆盖……)

最小圆覆盖:

初始圆为 点 11 这个半径为 00 的圆。。

for1ni=2for1_{i=2}^n 若 ii 不在已有圆中,则求一个圆周包含 ii 的最小圆。

{

~~~~~~ 圆改为点 ii 这个半径为 00 的圆

~~~~~~for2i−1j=1for2_{j=1}^{i-1} 若 jj 不在已有圆中,则求一个圆周包含 i、ji、j 的最小圆。

~~~~~~{

~~~~~~~~~~~~ 圆改为以线段 (i,j)(i,j) 为直径的圆

~~~~~~~~~~~~for2j−1k=1for2_{k=1}^{j-1} 若 kk 不在已有圆中,则求一个圆周包含 i、j、ki、j、k 的最小圆。

~~~~~~~~~~~~{

~~~~~~~~~~~~~~~~~~ 圆改为三角形 (i,j,k)(i,j,k) 的外接圆

~~~~~~~~~~~~}

~~~~~~}

}

返回圆

真是奇葩。QwQ

代码:

那个求三角形外心不妨自己乱搞,这里的那个是懒得推直接扒的,然后没看懂QwQ

#include <cmath>
#include <cstdio>
#include <iostream>
#include <algorithm>
#define N 501000
#define eps 1e-7
using namespace std;
struct Point
{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    void read(){scanf("%lf%lf",&x,&y);}
    bool operator < (const Point &A)const
    {return fabs(x-A.x)<eps?y<A.y:x<A.x;}
    double operator - (const Point &A)const
    {return sqrt((x-A.x)*(x-A.x)+(y-A.y)*(y-A.y));}
    void print(){printf("%.2lf %.2lf ",x,y);}
}p
;
struct Circle
{
    Point c; // center
    double r;
    Circle(Point _c=Point(0,0),double _r=0):c(_c),r(_r){}
    bool operator ^ (const Point &A)const{return A-c>r+eps;} // 包含
    void print()
    {
        c.print();
        printf("%.2lf\n",r);
    }
};
inline double xmul(const Point &A,const Point &B,const Point &C)
{return (C.y-A.y)*(B.x-A.x)-(B.y-A.y)*(C.x-A.x);}
struct Get_Convex_Hull
{//求凸包
    int stk1
,top1,stk2
,top2;
    Point tp
;
    void work(Point *p,int &n)
    {
        int i;
        sort(p+1,p+n+1);

        stk1[top1=1]=1;
        for(i=2;i<=n;i++)
        {
            while(top1>1&&xmul(p[stk1[top1-1]],p[stk1[top1]],p[i])>-eps)top1--;
            stk1[++top1]=i;
        }
        stk2[top2=1]=n;
        for(i=n-1;i;i--)
        {
            while(top2>1&&xmul(p[stk2[top2-1]],p[stk2[top2]],p[i])>-eps)top2--;
            stk2[++top2]=i;
        }
        n=0;
        for(i=1;i<top1;i++)tp[++n]=p[stk1[i]];
        for(i=1;i<top2;i++)tp[++n]=p[stk2[i]];
        for(i=1;i<=n;i++)p[i]=tp[i];
    }
}gch;
struct Get_Min_Circle_Cover
{
    Point circumcenter(const Point &a,const Point &b,const Point &c)
    {//返回三角形的外心 我并不知道这是什么鬼。。好强的样子。
        Point ret;
        double a1=b.x-a.x,b1=b.y-a.y,c1=(a1*a1+b1*b1)/2;
        double a2=c.x-a.x,b2=c.y-a.y,c2=(a2*a2+b2*b2)/2;
        double d=a1*b2-a2*b1;
        ret.x=a.x+(c1*b2-c2*b1)/d;
        ret.y=a.y+(a1*c2-a2*c1)/d;
        return ret;
    }
    Circle work(int n)
    {
        random_shuffle(p+1,p+n+1);
        Circle C=Circle(p[1],0);
        int i,j,k;

        for(i=2;i<=n;i++)if(C^p[i])
        {
            C=Circle(p[i],0);
            for(j=1;j<i;j++)if(C^p[j])
            {
                C.c=Point((p[i].x+p[j].x)/2,(p[i].y+p[j].y)/2);
                C.r=p[j]-C.c;
                for(k=1;k<j;k++)if(C^p[k])//求外接圆圆心,要求三点不能共线 
                    C.c=circumcenter(p[i],p[j],p[k]),C.r=C.c-p[i];

            }
        }
        return C;
    }
}gmcc;

int main()
{
//  freopen("test.in","r",stdin);

    int i=0,n;
    scanf("%d",&n);
    for(i=1;i<=n;i++)p[i].read();
//  gch.work(p,n);
    Circle ret=gmcc.work(n);
    ret.print();

    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: