JZOJ 3660. 【SHTSC2014】信号增幅仪
2018-01-31 22:07
316 查看
Description
无线网络基站在理想状况下有效信号覆盖范围是个圆形。而无线基站的功耗与圆的半径的平方成正比。现给出平面上若干网络用户的位置,请你选择一个合适的位置建设无线基站 ……就在你拿起键盘准备开始敲代码的时候,你的好朋友发明家SHTSC突然出现了。SHTSC刚刚完成了他的新发明——无线信号增幅仪。增幅仪能够在不增加无线基站功耗的前提下,使得有效信号的覆盖范围在某一特定方向上伸长若干倍。即:使用了增幅仪的无线基站覆盖范围是个椭圆,其功耗正比于半短轴长的平方。
现给出平面上若干网络用户的位置,请你选择一个合适的位置建设无线基站,并在增幅仪的帮助下使所有的用户都能接收到信号,且无线基站的功耗最小。
注意:由于SHTSC增幅仪的工作原理依赖地磁场,增幅的方向是恒定的。
Input
第一行一个整数:n。平面内的用户个数。之后的n行每行两个整数x, y,表示一个用户的位置。
第n+2行一个整数:a。表示增幅仪的增幅方向,单位是度。表示增幅仪的方向是从x正方向逆时针转a度。
第n+3行一个整数:p。表示增幅仪的放大倍数。
Output
输出一行一个实数,为能够覆盖所有用户的最小椭圆的半短轴长,四舍五入到三位小数。Sample Input
输入1:
21 0
-1 0
0
2
输入2:
31 1
-1 -1
0 0
45
7
Sample Output
输出1:
0.500输出2:
0.202Data Constraint
对于10%的数据,保证最优方案的中心在原点。对于20%的数据,保证点是随机生成的。
对于30%的数据,n≤100。
对于50%的数据,n≤5000。
对于100%的数据,n≤50000,0≤a<180,1≤p≤100,|x|,|y|≤2×10^8。
Solution
发现被拉长的“椭圆”和角度问题导致我们很难去统计答案。考虑简化它!
我们可以将角度 a 转正,再将每个点的纵坐标缩小 p 倍。
新的点的坐标可以通过三角函数的运算得出(画个图很好理解)。
这样就可以用一个正常的圆来覆盖这些点了,经典的最小圆覆盖问题。
现将点随机顺序,枚举每个点,在当前圆内就不管它。
若超出当前圆,则说明该点在新圆的边上。
以两点连线的中点作为新的圆的圆心,再继续枚举点。
若还是超出,则说明该点也在新圆的边上。
此时有三个点都在圆的边上,“三点确定一个圆”。
作出两条中垂线,再求其交点即可。
神奇的是,看上去是三重循环,但可证其时间复杂度是 O(N) 的。
Code
#include<cstdio> #include<algorithm> #include<cmath> #include<cctype> using namespace std; const int N=50005; const double Pi=acos(-1); struct node { double x,y; }a ,t,O; double R; inline int read() { int X=0,w=0; char ch=0; while(!isdigit(ch)) w|=ch=='-',ch=getchar(); while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } inline double sqr(double x) { return x*x; } inline double dist(node x,node y) { return sqrt(sqr(x.x-y.x)+sqr(x.y-y.y)); } inline bool incircle(node x) { return dist(O,x)<=R; } inline node midpoint(node x,node y) { t.x=(x.x+y.x)/2.0; t.y=(x.y+y.y)/2.0; return t; } inline void get(double &x,double &y,double &z,node xx,node yy) { if(xx.y==yy.y) { x=1.0,y=0.0,z=-(xx.x+yy.x)/2.0; }else if(xx.x==yy.x) { x=0.0,y=1.0,z=-(xx.y+yy.y)/2.0; }else { t=midpoint(xx,yy); double k=-1.0/((xx.y-yy.y)*1.0/(xx.x-yy.x)); x=k,y=-1.0,z=t.y-k*t.x; } } inline node work(node xx,node yy,node zz) { double a1=0,b1=0,c1=0,a2=0,b2=0,c2=0; get(a1,b1,c1,xx,yy); get(a2,b2,c2,yy,zz); t.y=-(a2*c1-a1*c2)/(b1*a2-b2*a1); t.x=(-c1-b1*t.y)/a1; return t; } int main() { int n=read(); for(int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(); double d=read()/180.0*Pi,p=read(); if(!d) { for(int i=1;i<=n;i++) { swap(a[i].x,a[i].y); a[i].x=-a[i].x; a[i].y=a[i].y*1.0/p; } }else if(d==Pi/2.0) { for(int i=1;i<=n;i++) a[i].y=a[i].y*1.0/p; }else { double si=sin(d),co=cos(d),ta=tan(d); for(int i=1;i<=n;i++) { double z=a[i].x-a[i].y/ta; t.x=z*si; t.y=a[i].y/si+z*co; t.y=t.y*1.0/p; a[i]=t; } } random_shuffle(a+1,a+1+n); for(int i=1;i<=n;i++) if(!incircle(a[i])) { O=a[i],R=0; for(int j=1;j<i;j++) if(!incircle(a[j])) { O=midpoint(a[i],a[j]); R=dist(O,a[i]); for(int k=1;k<j;k++) if(!incircle(a[k])) { O=work(a[i],a[j],a[k]); R=dist(O,a[i]); } } } printf("%.3lf",R); return 0; }
相关文章推荐
- jzoj 3660. 【SHTSC2014】信号增幅仪
- JZOJ-senior-3660. 【SHTSC2014】信号增幅仪(amplifier)
- 【SHTSC2014】信号增幅仪
- 【SHTSC2014】信号增幅仪
- 【JZOJ3663】【SHTSC2014】神奇化合物(compound) (最小生成树+并查集)
- 【bzoj3564】 [SHOI2014]信号增幅仪
- 【SHTSC2014】信号增幅仪
- 【SHTSC2014】信号增幅仪
- BZOJ3564.【SHTSC2014】信号增幅仪(amplifier)
- [SHOI2014]信号增幅仪
- 【JZOJ3664】【SHTSC2014】三叉神经树(neuron) (树链剖分 or LCT)
- 【jzoj3661】【SHTSC2014】【概率充电器】【期望】
- bzoj3564 [SHOI2014]信号增幅仪
- BZOJ 3564: [SHOI2014]信号增幅仪
- bzoj3564: [SHOI2014]信号增幅仪
- jzoj 3661. 【SHTSC2014】概率充电器
- January 31st 模拟赛A T2 【SHTSC2014】信号增幅仪 Solution
- JZOJ 3807. 【NOIP2014模拟8.25】地砖铺设
- {题解}[jzoj3396] 【NOIP2013模拟】Rainbow的信号
- jzoj3542 【清华集训2014】冒泡排序 (又是性质+半构造)