BZOJ3564.【SHTSC2014】信号增幅仪(amplifier)

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。

题解

椭圆是斜的,计算起来非常不方便,
于是就应该把它旋转成为正的。
旋转公式:

xx=x*cos(a)-y*sin(a);
yy=x*sin(a)+y*cos(a);

现在椭圆是正的了,
就应该想办法把它变为熟悉圆。
根据题目的意思只需要将旋转过后的x轴坐标除以p。

现在问题就转变成为了熟悉的最小圆覆盖问题。

在这道题目里面,主要是要转化问题。

code

#include<queue>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <time.h>
#define ll long long
#define N 50003
#define M 103
#define db double
#define P putchar
#define G getchar
#define inf 998244353
using namespace std;
char ch;
int read()
{
    int n=0;
    ch=G();
    while((ch<'0' || ch>'9') && ch!='-')ch=G();
    ll w=1;
    if(ch=='-')w=-1,ch=G();
    while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
    n*=w;
}

int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
ll abs(ll x){return x<0?-x:x;}
db sqr(db x){return x*x;}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}

db x[N],y[N],xx,yy,O_x,O_y,O_r;
db A,B,C,GG,a,p; 
int n;
bool bz[N];

db dis(db x,db y,db xx,db yy)
{
    return sqrt(sqr(x-xx)+sqr(y-yy));
}

bool pin(db x,db y)
{
    return dis(x,y,O_x,O_y)<=O_r?1:0;
}

int main()
{
    freopen("amplifier.in","r",stdin);
    freopen("amplifier.out","w",stdout);
    n=read();
    for(int i=1;i<=n;i++)
        x[i]=read(),y[i]=read();
    a=read();
    p=read();
    a=360-a;
    a=a*3.1415926535898/180;
    for(int i=1;i<=n;i++)
    {
        xx=x[i]*cos(a)-y[i]*sin(a);
        yy=x[i]*sin(a)+y[i]*cos(a);
        x[i]=xx/p;
        y[i]=yy;
    }

    for(int i=1;i<=n;i++)
        if(!pin(x[i],y[i]))
        {
            O_x=x[i];O_y=y[i];O_r=0;
            for(int j=1;j<i;j++)
                if(!pin(x[j],y[j])) 
                {
                    O_x=(x[i]+x[j])/2;
                    O_y=(y[i]+y[j])/2;
                    O_r=dis(O_x,O_y,x[i],y[i]);
                    for(int k=1;k<j;k++)
                        if(!pin(x[k],y[k]))
                        {
                            A=sqr(x[i])+sqr(y[i]);
                            B=sqr(x[j])+sqr(y[j]);
                            C=sqr(x[k])+sqr(y[k]);
                            GG=(y[k]-y[j])*x[i]+(y[i]-y[k])*x[j]+(y[j]-y[i])*x[k];
                            O_x=((B-C)*y[i]+(C-A)*y[j]+(A-B)*y[k])/(2*GG);
                            O_y=((C-B)*x[i]+(A-C)*x[j]+(B-A)*x[k])/(2*GG);
                            O_r=dis(O_x,O_y,x[i],y[i]);
                        }
                }
        }
    printf("%.3lf",O_r);

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值