【SHTSC2014】信号增幅仪

Description

无线网络基站在理想状况下有效信号覆盖范围是个圆形。而无线基站的功耗与圆的半径的平方成正比。现给出平面上若干网络用户的位置,请你选择一个合适的位置建设无线基站 ……

就在你拿起键盘准备开始敲代码的时候,你的好朋友发明家SHTSC突然出现了。SHTSC刚刚完成了他的新发明——无线信号增幅仪。增幅仪能够在不增加无线基站功耗的前提下,使得有效信号的覆盖范围在某一特定方向上伸长若干倍。即:使用了增幅仪的无线基站覆盖范围是个椭圆,其功耗正比于半短轴长的平方。

现给出平面上若干网络用户的位置,请你选择一个合适的位置建设无线基站,并在增幅仪的帮助下使所有的用户都能接收到信号,且无线基站的功耗最小。

注意:由于SHTSC增幅仪的工作原理依赖地磁场,增幅的方向是恒定的。

Input

第一行一个整数:n。平面内的用户个数。

之后的n行每行两个整数x, y,表示一个用户的位置。

第n+2行一个整数:a。表示增幅仪的增幅方向,单位是度。表示增幅仪的方向是从x正方向逆时针转a度。

第n+3行一个整数:p。表示增幅仪的放大倍数。

Output

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

Sample Input
输入1:
2
1 0
-1 0
0
2
输入2:
3
1 1
-1 -1
0 0
45
7
Sample Output
输出1:
0.500
输出2:
0.202
Data Constraint
对于10%的数据,保证最优方案的中心在原点。
对于20%的数据,保证点是随机生成的。
对于30%的数据,n≤100。
对于50%的数据,n≤5000。
对于100%的数据,n≤50000,0≤a<180,1≤p≤100,|x|,|y|≤2×10^8。

The Solution

我们先将所有点绕原点顺时针旋转α度,那么椭圆就被转正了.
再将每个点的x坐标分别缩小p倍,将问题转化为经典的最小圆覆盖问题.

关于最小圆覆盖问题,我找个时间会写个博客
蒟蒻

参考程序

#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#define fo(i,a,b) for (int i=a;i<=b;i++)
#define fd(i,a,b) for (int i=a;i>=b;i--)
#define PI 3.14159265358979323846  
#define N 510000  
#define EPS (1E-20)  

using namespace std;

typedef double db;

struct Hownone
{
    db x,y;
    Hownone(db xx = 0,db yy = 0) {x = xx,y = yy;}
    Hownone operator - (Hownone a) {return Hownone(x - a.x,y - a.y);}
    Hownone operator + (Hownone a) {return Hownone(x + a.x,y + a.y);}
    db operator * (Hownone a) {return x * a.y - y * a.x;}
    Hownone operator * (db b) {return Hownone(x * b,y * b);}
    Hownone operator / (db b) {return Hownone(x / b,y / b);}
    Hownone Rotate(db Alpha) {return Hownone(x * cos(Alpha) + y * sin(Alpha),-x * sin(Alpha) + y * cos(Alpha));} ////绕原点顺时针旋转α度  
    Hownone Opp() {return Hownone(-y,x);}
}Dots[N];

int n;

int Check(db x)
{
    if (fabs(x) < EPS) return 0;
    if (x > EPS) return 1;
    return -1;
}

db Sqr(db x) {return x * x;}

db Dist(Hownone a,Hownone b)//求点a到点b距离  
{
    return sqrt(Sqr(a.x - b.x) + Sqr(a.y - b.y));
}

Hownone Calc(Hownone A,Hownone B,Hownone C)
{
    Hownone Res;
    db a1 = B.x - A.x,
       b1 = B.y - A.y,
       c1 = (Sqr(a1) + Sqr(b1)) / 2,
       a2 = C.x - A.x,
       b2 = C.y - A.y,
       c2 = (Sqr(a2) + Sqr(b2)) / 2,
       d = a1 * b2 - a2 * b1;
    Res.x = A.x + (c1 * b2 - c2 * b1) / d;
    Res.y = A.y + (a1 * c2 - a2 * c1) / d;
    return Res;
}

int main()
{
    freopen("amplifier.in","r",stdin);
    freopen("amplifier.out","w",stdout);
    db Alpha,Scale;
    scanf("%d",&n);
    fo(i,1,n) scanf("%lf%lf",&Dots[i].x,&Dots[i].y);
    scanf("%lf%lf",&Alpha,&Scale);
    Alpha = Alpha / 180 * PI;
    fo(i,1,n)
    {
        Dots[i] = Dots[i].Rotate(Alpha);
        Dots[i].x /= Scale;
    }
    db R = 0;//R=三角形的外接圆半径  
    Hownone c = Dots[1];
    fo(i,2,n)
        if (Dist(Dots[i],c) > R + EPS)
        {
            c = Dots[i];
            R = 0;
            fo(j,1,i - 1)
            {
                if (Dist(Dots[j],c) > R + EPS)
                {
                    c = (Dots[i] + Dots[j]) / 2;
                    R = Dist(Dots[j],c);
                    fo(k,1,j - 1)
                    {
                        if (Dist(Dots[k],c) > R + EPS)
                        {
                            c = Calc(Dots[i],Dots[j],Dots[k]);
                            R = Dist(Dots[i],c);    
                        }   
                    }
                }
            }
        }
    printf("%.3lf\n",R);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值