【bzoj2823】 AHOI2012—信号塔

原创 2016年08月30日 11:45:30

http://www.lydsy.com/JudgeOnline/problem.php?id=2823 (题目链接)

题意:求最小圆覆盖

Solution
  关于最小圆覆盖的做法,论文里面都有。其实真正麻烦的是求三角形的外心。
  
给定a(x1,y1) b(x2,y2) c(x3,y3)求外接圆心坐标O(x,y)。

1. 首先,外接圆的圆心是三角形三条边的垂直平分线的交点,我们根据圆心到顶点的距离相等,可以列出以下方程:

   (x1-x)*(x1-x)-(y1-y)*(y1-y)=(x2-x)*(x2-x)+(y2-y)*(y2-y);

   (x2-x)*(x2-x)+(y2-y)*(y2-y)=(x3-x)*(x3-x)+(y3-y)*(y3-y);

2.化简得到:

    2*(x2-x1)*x+2*(y2-y1)y=x2^2+y2^2-x1^2-y1^2;

    2*(x3-x2)*x+2*(y3-y2)y=x3^2+y3^2-x2^2-y2^2;

    令A1=2*(x2-x1);

        B1=2*(y2-y1);

        C1=x2^2+y2^2-x1^2-y1^2;

        A2=2*(x3-x2);

        B2=2*(y3-y2);

        C2=x3^2+y3^2-x2^2-y2^2;

        即

            A1*x+B1y=C1;

            A2*x+B2y=C2;

3.最后根据克拉默法则:

      x=((C1*B2)-(C2*B1))/((A1*B2)-(A2*B1));

      y=((A1*C2)-(A2*C1))/((A1*B2)-(A2*B1));

因此,x,y为最终结果;

代码:

// bzoj2823
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<vector>
#define eps 1e-10
#define inf 2147483640
#define LL long long
#define free(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout);
using namespace std;
inline LL getint() {
    LL x=0,f=1;char ch=getchar();
    while (ch>'9' || ch<'0') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

const int maxn=1000010;
struct point {double x,y;}p[maxn];
int n;

double dis(point a,point b) {
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
point center(point a,point b,point c) {
    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;
    return (point){a.x+(c1*b2-c2*b1)/d,a.y+(a1*c2-a2*c1)/d};
}
int main() {
    scanf("%d",&n);
    for (int i=1;i<=n;i++) {scanf("%lf%lf",&p[i].x,&p[i].y);swap(p[i],p[rand()%i+1]);}
    point c=p[1];double r=0;
    for (int i=2;i<=n;i++) {
        if (dis(c,p[i])<=r+eps) continue;
        c=p[i];r=0;
        for (int j=1;j<i;j++) {
            if (dis(c,p[j])<=r+eps) continue;
            c.x=(p[i].x+p[j].x)/2;
            c.y=(p[i].y+p[j].y)/2;
            r=dis(c,p[j]);
            for (int k=1;k<j;k++) {
                if (dis(c,p[k])<=r+eps) continue;
                c=center(p[i],p[j],p[k]);
                r=dis(p[k],c);
            }
        }
    }
    printf("%.2f %.2f %.2f",c.x,c.y,r);
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

bzoj2823: [AHOI2012]信号塔

随机增量法求最小覆盖圆

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

题解之前: 首先最小圆覆盖虽然有三层 forfor 循环,但是它是期望 O(n)O(n) 的。什么?你问我为啥?那我只能呵呵了,50W的 O(n3)O(n^3) 高速跑过。 后交的是不求凸包直...
  • Vmurder
  • Vmurder
  • 2015年06月23日 14:04
  • 1264

bzoj2823[AHOI2012]信号塔

随机增量法求最小覆盖圆,主要就是圆心坐标神烦,后来看到了ACdreamer的一个简洁版本,虽然还没明白是为什么但是比窝那个短多了 #include #include #include #includ...
  • BPM136
  • BPM136
  • 2015年12月05日 11:28
  • 192

【BZOJ 2823】 [AHOI2012]信号塔

随机增量法求最小圆覆盖~ (三倍经验题。。)

BZOJ 2823 AHOI2012 信号塔 计算几何

题目大意:给定n个点(n 逗我?n 其实数据是随机生成的 经过验证 随机生成50w的点集 平均在凸包上的点在50~60个左右 于是求凸包之后就可以随便乱搞了- - 不会写O(n^3)的最小圆覆盖...
  • PoPoQQQ
  • PoPoQQQ
  • 2014年12月26日 16:55
  • 1293

【bzoj2823】【AHOI2012】【信号塔】【随机增量法】

Description 在野外训练中,为了确保每位参加集训的成员安全,实时的掌握和收集周边环境和队员信息非常重要,集训队采用的方式是在训练所在地散布N个小型传感器来收集并传递信息,这些传感器只与...

bzoj2823【AHOI2012】信号塔

随机增量法求最小圆覆盖

BZOJ 2823 AHOI 2012 信号塔 凸包+最小圆覆盖

题目大意:给出平面上n个点,求最小圆覆盖。 思路:圆覆盖问题只与所有点中凸包上的点有关,因此先求一下凸包,然后数据范围骤减。大概是只剩下logn左右个点。这样就可以随便浪了。 先找所有三个...

BZOJ 2823: [AHOI2012]信号塔 随机增量法

2823: [AHOI2012]信号塔 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1063  Solved: 488 [Submit][S...

bzoj2823 信号塔 随机增量算法

看WC课件好像zhj的ppt里面有这道题目?然而讲得太简略了看不懂。        然后扒了扒黄学长的代码发现好像很简单。。。        实际上就是暴力枚举三个点,枚举到第i个点时看能不能放到当前...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【bzoj2823】 AHOI2012—信号塔
举报原因:
原因补充:

(最多只允许输入30个字)