JZOJ 3660. 【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。
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[N],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;}elseif(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;}}elseif(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 3129. 【WinterCa
- 下一篇: JZOJ 3786. 【NOI2015模