January 31st 模拟赛A T2 SHTSC2014信号增幅仪 Solution

Posted ace-killing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了January 31st 模拟赛A T2 SHTSC2014信号增幅仪 Solution相关的知识,希望对你有一定的参考价值。

题目空降

Description

无线网络基站在理想状况下有效信号覆盖范围是个圆形。而无线基站的功耗与圆的半径的平方成正比。现给出平面上若干网络用户的位置,请你选择一个合适的位置建设无线基站 ……
就在你拿起键盘准备开始敲代码的时候,你的好朋友发明家SHTSC突然出现了。SHTSC刚刚完成了他的新发明——无线信号增幅仪。增幅仪能够在不增加无线基站功耗的前提下,使得有效信号的覆盖范围在某一特定方向上伸长若干倍。即:使用了增幅仪的无线基站覆盖范围是个椭圆,其功耗正比于半短轴长的平方。
现给出平面上若干网络用户的位置,请你选择一个合适的位置建设无线基站,并在增幅仪的帮助下使所有的用户都能接收到信号,且无线基站的功耗最小。
注意:由于SHTSC增幅仪的工作原理依赖地磁场,增幅的方向是恒定的。

Input

第一行一个整数:\(n\)。平面内的用户个数。
之后的\(n\)行每行两个整数\(x, y\),表示一个用户的位置。
\(n+2\)行一个整数:\(a\)。表示增幅仪的增幅方向,单位是度。表示增幅仪的方向是从\(x\)正方向逆时针转\(a\)度。
\(n+3\)行一个整数:\(p\)。表示增幅仪的放大倍数。

Output

输出一行一个实数,为能够覆盖所有用户的最小椭圆的半短轴长,四舍五入到三位小数。

Analysis

貌似超出我的能力范围。
对于一个平面直角坐标系上有\(n\)个点,求一个短半轴\(A=r\)、长半轴\(B=pr\)且长半轴所在直线为\(x\)轴逆时针旋转\(a^\circ\)的,\(r\)最小的能覆盖这\(n\)个点的椭圆。
(觉得难懂的话请自行脑补题面)
技术分享图片
其实我们可以将所有元素顺时针旋转\(a^\circ\)
技术分享图片
再讲\(x\)轴的单位长度扩大为\(p\)(即将所有点横坐标除以\(p\)
技术分享图片
问题转化为最小覆盖圆问题。(蒟蒻水平有限,请自行百度)
跳转dalao‘s blog

Code

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define pi 3.14159265359
using namespace std;

struct Dot
{
    double x, y;
    Dot(double _x = 0, double _y = 0)
    {
        x = _x, y = _y;
    }
};

struct Line
{
    Dot p, v;
    Line() {}
    Line(Dot _p, Dot _v)
    {
        p = _p, v = _v;
    }
};

int n;
double r;
Dot d[50005];
Dot core;
double a, p;

Dot operator+(Dot a, Dot b) {return Dot(a.x + b.x, a.y + b.y);}
Dot operator-(Dot a, Dot b) {return Dot(a.x - b.x, a.y - b.y);}
Dot operator*(Dot a, double b) {return Dot(a.x * b, a.y * b);}
double DotTimes(Dot a, Dot b) {return a.x * b.x + a.y * b.y;}
double CrossTimes(Dot a, Dot b) {return a.x * b.y - a.y * b.x;}
double Len(Dot t) {return sqrt(DotTimes(t, t));}
Dot Adjust(Dot a, double b) {return a * (b / Len(a));}
double Dist(Dot a, Dot b) {return Len(a - b);}
Dot Prep(Dot a) {return Dot(-a.y, a.x);}
Dot Intersect(Line a, Line b) {return b.p + b.v * (CrossTimes(a.v, a.p - b.p) / CrossTimes(a.v, b.v));}
Dot Angle(double a) {return Dot(cos(a), sin(a));}
Dot operator*(Dot a, Dot b) {return Dot(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);}
Dot Rotate(Dot a, double b) {return a * Angle(b);}

Dot Circumcenter(Dot a, Dot b, Dot c)
{
    Line p = Line(a, b - a), q = Line(a, c - a);
    p.p = p.p + p.v * 0.5, q.p = q.p + q.v * 0.5;
    p.v = Prep(p.v), q.v = Prep(q.v);
    return Intersect(p, q);
}

void Min_Cover_Circle()
{
    random_shuffle(d + 1, d + n + 1);
    Dot c;
    c = d[1], r = 0;

    for (int i = 2; i <= n; i++)
    {
        if (Dist(d[i], c) > r)
        {
            c = d[i]; r = 0;

            for (int j = 1; j < i; j++)
                if (Dist(d[j], c) > r)
                {
                    c.x = (d[i].x + d[j].x) / 2;
                    c.y = (d[i].y + d[j].y) / 2;
                    r = Dist(d[j], c);

                    for (int k = 1; k < j; k++)
                        if (Dist(d[k], c) > r)
                        {
                            c = Circumcenter(d[i], d[j], d[k]);
                            r = Dist(d[i], c);
                        }
                }
        }
    }
}

int main(int argc, char const *argv[])
{
    freopen("init.in", "r", stdin);
    //freopen("amplifier.out", "w", stdout);
    scanf("%d", &n);

    for (int i = 1; i <= n; i++)
        scanf("%lf%lf", &d[i].x, &d[i].y);

    scanf("%lf%lf", &a, &p);

    for (int i = 1; i <= n; i++)
    {
        d[i] = Rotate(d[i], (180 - a) * pi / 180);
        d[i].x /= p;
    }

    Min_Cover_Circle();
    printf("%.3lf\n", r);
    return 0;
}

以上是关于January 31st 模拟赛A T2 SHTSC2014信号增幅仪 Solution的主要内容,如果未能解决你的问题,请参考以下文章

January 24th 模拟赛A T3NOI2014模拟数列 Solution

January 02 2017 Week 1st Monday

January 05 2017 Week 1st Thursday

January 01 2017 Week 1st Sunday

深圳双合SHTS2000对时装置有没有北斗功能

January 05th, 2018 Week 01st Friday