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。
Analysis
怎麼做呢?
考慮一波玄學操作
把座標軸翻轉過來(要用到一波三角函數的知識),使得x軸和被增長方向重合
然後,放大就等於把每個點的橫座標縮小
這個時候 這個問題就變成了一個最小圓覆蓋問題
可以運用隨機化算法來解決 看似n^3的寫法在實際上其實是o(n)的
具體就是很暴力的操作
考慮兩個點在圓上還是三個點在圓上(求外心即可)
Code
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define db double
using namespace std;
typedef long long ll;
const int maxn=50005;
const double pi=acos(-1);
struct edge{
db x,y;
} a[maxn];
int n,i,x,y,d,p;
db r;
int read(){
int sum=0;
char c=getchar(); int p=1;
while (c<'0'||c>'9'){
if (c=='-') p=-1;
c=getchar();
}
while (c>='0'&&c<='9'){
sum=sum*10+c-'0';
c=getchar();
}
return sum*p;
}
db dis(edge a,edge b){a.x=a.x-b.x; a.y=a.y-b.y; return sqrt(a.x*a.x+a.y*a.y);}
edge rot(edge t,int p){
db tri=1.0*p/180*pi; edge h;
h.x=t.x*cos(tri)-t.y*sin(tri);
h.y=t.x*sin(tri)+t.y*cos(tri);
return h;
}
edge centre(edge A,edge B,edge C){
db a1=B.x-A.x,b1=B.y-A.y,c1=(a1*a1+b1*b1)/2;
db a2=C.x-A.x,b2=C.y-A.y,c2=(a2*a2+b2*b2)/2;
db d=a1*b2-b1*a2;edge ret;
ret.x=A.x+(c1*b2-c2*b1)/d;
ret.y=A.y+(c2*a1-c1*a2)/d;
return ret;
}
void get(){
int i,j,k;
random_shuffle(a+1,a+n+1);
edge c=a[1];r=0;
fo(i,1,n){
if (dis(a[i],c)<=r) continue;
c=a[i],r=0;
fo(j,1,i-1) {
if (dis(a[j],c)<=r) continue;
c.x=(a[i].x+a[j].x)/2,c.y=(a[i].y+a[j].y)/2;
r=dis(a[j],c);
fo(k,1,j-1){
if (dis(a[k],c)<=r) continue;
c=centre(a[i],a[j],a[k]);
r=dis(a[i],c);
}
}
}
}
int main(){
freopen("amplifier.in","r",stdin);
freopen("amplifier.out","w",stdout);
scanf("%d",&n);
fo(i,1,n) {
x=read(),y=read();
a[i].x=x*1.0,a[i].y=y*1.0;
}
scanf("%d%d",&d,&p);
fo(i,1,n) a[i]=rot(a[i],-d),a[i].x/=p;
get();
printf("%.3lf\n",r);
}