无线网络基站在理想状况下有效信号覆盖范围是个圆形。而无线基站的功耗与圆的半径的平方成正比。
现给出平面上若干网络用户的位置,请你选择一个合适的位置建设无线基站….
就在你拿起键盘准备开始敲代码的时候,你的好朋友发明家 SHTSC 突然出现了。SHTSC 刚刚完成了他的新发明——无线信号增幅仪。增幅仪能够在不增加无线基站功耗的前提下,使得有效信号的覆盖范围在某一特定方向上伸长若干倍。即:使用了增幅仪的无线基站覆盖范围是个椭圆,其功耗正比于半短轴长的平方。现给出平面上若干网络用户的位置,请你选择一个合适的位置建设无线基站,并在增幅仪的帮助下使所有的用户都能接收到信号,且无线基站的功耗最小。
注意:由于 SHTSC 增幅仪的工作原理依赖地磁场,增幅的方向是恒定的。
输入格式:
第一行一个整数:n。平面内的用户个数。
之后的 n 行每行两个整数 x, y,表示一个用户的位置。
第 n+2 行一个整数:a。表示增幅仪的增幅方向,单位是度。表示增幅仪的方向是从 x 正方向逆时针转 a 度。
第 n+3 行一个整数:p。表示增幅仪的放大倍数。
输出格式:
输出一行一个实数,为能够覆盖所有用户的最小椭圆的半短轴长,四舍五入到三位小数。
样例输入:
3
1 1
-1 -1
0 0
45
7
样例输出:
0.202
数据范围:
对于 10%的数据,n≤5
对于 30%的数据,n≤50
对于 50%的数据,n≤200
对于 70%的数据,n≤1000
对于 100%的数据,n≤50000, 0≤a<180, 1≤p≤100, |x|,|y|≤2×108。
时间限制:
1s
空间限制:
256MB
本题是一道不错的计算几何题。先是一个特殊处理,把我们的坐标轴x轴转到 与增量方向一致(具体做法是往反方向旋转点),然后就可以直接把x轴除以该倍数就变成了一个圆,然后就是裸的最小圆覆盖。用随机迭代增量法找到最小覆盖圆,均摊复杂度O(n)
最小圆覆盖的方法已get就是三重循环好理解
今天还手证了一下一点绕定点旋转公式(不要怕设B∠)并手推了一下 三点确定圆心,圆的半径的做法.程序中要仔细看清楚,手推时要单独拉出来调程。
本题卡精度!!!!!!!!!!
C++三角函数pi 用acos(-1)得到。
C++内部三角函数用的都是弧度
#include<bits/stdc++.h>
using namespace std;
#define N 50001
struct NODE{
double x,y;
}V[N];
double x,y,r;
double eps=1e-8;
int n;
#define F(i,a,b) for(int i=a;i<=b;i++)
double du;
const double pi=acos(-1);
double bei;
double dis(double x1,double y1,double x2,double y2)
{
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
bool yuannei(NODE kk){return dis(kk.x,kk.y,x,y)-eps<=r;}
void solve(NODE a,NODE b,NODE c)
{
double x1=a.x,x2=b.x,x3=c.x,y1=a.y,y2=b.y,y3=c.y;
double a1,b1,c1,a2,b2,c2,a3,b3,c3;
double xm,ym;
xm=(x1+x2)/2;ym=(y1+y2)/2;
a1=y2-y1;b1=x1-x2;swap(a1,b1);b1=-b1;c1=-(xm*a1+ym*b1);
xm=(x1+x3)/2;ym=(y1+y3)/2;
a2=y3-y1;b2=x1-x3;swap(a2,b2);b2=-b2;c2=-(xm*a2+ym*b2);
x=(c2*b1-c1*b2)/(a1*b2-a2*b1);y=(-a1*x-c1)/b1;
r=dis(a.x,a.y,x,y);
}
NODE xuan(NODE o,double alpha,NODE p)
{
NODE tp;
p.x-=o.x;
p.y-=o.y;
tp.x=p.x*cos(alpha)-p.y*sin(alpha)+o.x+eps;
tp.y=p.y*cos(alpha)+p.x*sin(alpha)+o.y+eps;//手推即可,beta最后会约掉
return tp;
}
int main()
{
scanf("%d",&n);
F(i,1,n){scanf("%lf%lf",&V[i].x,&V[i].y);}
cin>>du>>bei;
du=-du/180.0*pi;
F(i,1,n)
{
NODE o;
o.x=0;o.y=0;
V[i]=xuan(o,du,V[i]);//每个点转负的,相当于坐标轴转正的。
V[i].x/=bei;
}
random_shuffle(V+1,V+n+1);
x=0;y=0;r=0;
F(i,1,n)
{
if(!yuannei(V[i]))
{
x=V[i].x;y=V[i].y;r=0;
F(j,1,i-1)
{
if(!yuannei(V[j]))
{
x=(V[i].x+V[j].x)/2;y=(V[i].y+V[j].y)/2;
r=dis(V[i].x,V[i].y,x,y);
F(k,1,j-1)
{
if(!yuannei(V[k])) solve(V[i],V[j],V[k]);
}
}
}
}
}
printf("%.3lf",r+eps);
//要加个eps才能够A。
}