码迷,mamicode.com
首页 > 其他好文 > 详细

【AHOI2012】信号塔

时间:2019-01-30 11:11:36      阅读:130      评论:0      收藏:0      [点我收藏+]

标签:section   覆盖   cti   gis   http   ==   show   register   cstring   

题面

题解

xgzc怒切计算几何

最小圆覆盖板子题

整体算法如下:

枚举第一个点,考虑当前圆是否包含了这个点,如果没有,则把圆变成以这个点为圆心,半径为\(0\)的圆。再枚举第二个点,考虑圆是否包含了这个点,如果没有,则把圆变成以这两个点的中点为圆心,半径为两点距离一半的圆。再枚举第三个点,节点是否在圆内,如果不在,则把圆直接变成这三个点的外接圆。

\(n^3\)过百万???是的

我们随机打乱点,这样的期望是\(O(n)\)

代码

#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<algorithm>
#define RG register
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define clear(x, y) memset(x, y, sizeof(x))

inline int read()
{
    int data = 0, w = 1; char ch = getchar();
    while(ch != '-' && (!isdigit(ch))) ch = getchar();
    if(ch == '-') w = -1, ch = getchar();
    while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
    return data * w;
}

const int maxn(1e6 + 10);
const double eps(1e-10), pi(acos(-1));
struct point { double x, y; };
struct line { point a, v; };
struct circle { point o; double r; } O;
typedef point vector;
inline vector operator + (const vector &lhs, const vector &rhs)
    { return (vector) {lhs.x + rhs.x, lhs.y + rhs.y}; }
inline vector operator - (const vector &lhs, const vector &rhs)
    { return (vector) {lhs.x - rhs.x, lhs.y - rhs.y}; }
inline vector operator * (const vector &lhs, const double &rhs)
    { return (vector) {lhs.x * rhs, lhs.y * rhs}; }
inline vector operator / (const vector &lhs, const double &rhs)
    { return (vector) {lhs.x / rhs, lhs.y / rhs}; }
inline double operator * (const vector &lhs, const vector &rhs)
    { return lhs.x * rhs.x + lhs.y * rhs.y; }
inline double cross(const vector &lhs, const vector &rhs)
    { return lhs.x * rhs.y - lhs.y * rhs.x; }
inline double Len(const vector &a) { return sqrt(a.x * a.x + a.y * a.y); }
inline double Dis(const point &a, const point &b) { return Len(a - b); }
inline vector rotate(const vector &lhs, const double &ang)
{
    double c = cos(ang), s = sin(ang);
    return (vector) {lhs.x * c - lhs.y * s, lhs.x * s + lhs.y * c};
}

point Intersection(const line &a, const line &b)
{
    vector c = b.a - a.a;
    double t = cross(b.v, c) / cross(b.v, a.v);
    return a.a + a.v * t;
}

line half(const line &a)
{
    point b = a.a + a.v * .5;
    return (line) {b, rotate(a.v, pi * .5)};
}

void getCircle(point p[], int n)
{
    std::random_shuffle(p + 1, p + n + 1);
    for(RG int i = 1; i <= n; ++i)
        if(Dis(O.o, p[i]) > O.r)
        {
            O.o = p[i], O.r = 0;
            for(RG int j = 1; j < i; j++)
                if(Dis(O.o, p[j]) > O.r)
                {
                    O.o = (p[i] + p[j]) * .5, O.r = Dis(p[i], p[j]) * .5;
                    for(RG int k = 1; k < j; k++)
                        if(Dis(O.o, p[k]) > O.r)
                            O.o = Intersection(half((line) {p[i], p[j] - p[i]}),
                                    half((line) {p[i], p[k] - p[i]})),
                            O.r = Dis(O.o, p[i]);
                }
        }
    printf("%.2lf %.2lf %.2lf\n", O.o.x, O.o.y, O.r);
}

int n; point p[maxn];
int main()
{
    srand(time(NULL)); scanf("%d", &n);
    for(RG int i = 1; i <= n; i++) scanf("%lf%lf", &p[i].x, &p[i].y);
    getCircle(p, n);
    return 0;
}

【AHOI2012】信号塔

标签:section   覆盖   cti   gis   http   ==   show   register   cstring   

原文地址:https://www.cnblogs.com/cj-xxz/p/10336956.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!