【题目描述】:
无线网络基站在理想状况下有效信号覆盖范围是个圆形。而无线基站的功耗与圆的半径的平方成正比。
现给出平面上若干网络用户的位置,请你选择一个合适的位置建设无线基站....
就在你拿起键盘准备开始敲代码的时候,你的好朋友发明家 SHTSC 突然出现了。SHTSC 刚刚完成了他的新发明——无线信号增幅仪。增幅仪能够在不增加无线基站功耗的前提下,使得有效信号的覆盖范围在某一特定方向上伸长若干倍。即:使用了增幅仪的无线基站覆盖范围是个椭圆,其功耗正比于半短轴长的平方。现给出平面上若干网络用户的位置,请你选择一个合适的位置建设无线基站,并在增幅仪的帮助下使所有的用户都能接收到信号,且无线基站的功耗最小。
注意:由于SHTSC 增幅仪的工作原理依赖地磁场,增幅的方向是恒定的。
【题目解法】:
显然最小椭圆覆盖是很难实现的
我们可以把点顺时针旋转a度,然后x坐标缩短为1/p,就可以把覆盖变成圆形了
然后就是最小圆覆盖了,模拟退火估计也是可以的
复杂度O(N)
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <iomanip>
#define sqr(x) ((x)*(x))
using namespace std;
const int N=50005;
const long double zero=1e-8;
const long double pi=acos(-1.0);
struct node {long double x,y,r;} a[N];
struct line {long double A,B,C;};
int n; long double A,B; node ans;
inline long long getint()
{
long long x=0; char c=getchar(); bool flag=false;
while ((c!='-')&&((c<'0')||(c>'9'))) c=getchar();
if (c=='-') flag=true,c=getchar();
while ((c>='0')&&(c<='9')) x=x*10+(long long)(c-'0'),c=getchar();
if (flag) return -x; else return x;
}
void init()
{
n=getint();
for (int i=1; i<=n; i++) cin >> a[i].x >> a[i].y;
cin >> A; cin >> B; A=A*pi/180.0;
/*
x=rcosB y=rsinB
x'=rcos(B-A)=rcosAcosB+rsinAsinB=xcosA+ysinA
y'=rsin(B-A)=rsinBcosA-rsinAcosB=ycosA-xsinA
*/
for (int i=1; i<=n; i++)
{
long double x=a[i].x,y=a[i].y; a[i].r=0;
a[i].x=x*cos(A)+y*sin(A);
a[i].y=y*cos(A)-x*sin(A);
a[i].x/=B;
}
}
inline int dcmp(long double x)
{
if (x>zero) return 1;
if (x<-zero) return -1;
return 0;
}
inline long double dist(node A,node B)
{
return sqrt(sqr(A.x-B.x)+sqr(A.y-B.y));
}
inline node centre(node A,node B)
{
long double x=(A.x+B.x)/2,y=(A.y+B.y)/2;
return (node){x,y,dist(A,B)/2};
}
inline line mid_vertical(node A,node B)
{
//(B.x-A.x)/(A.y-B.y)*(x-x')+y'=y
long double x=(A.x+B.x)/2,y=(A.y+B.y)/2; line now;
now.A=B.x-A.x; now.B=B.y-A.y;
now.C=-now.A*x-now.B*y; return now;
}
inline node centre(node A,node B,node C)
{
line X=mid_vertical(A,B),Y=mid_vertical(B,C);
if (X.A*Y.B==X.B*Y.A)
{
long double distAB=dist(A,B);
long double distAC=dist(A,C);
long double distBC=dist(B,C);
long double dis=max(distAB,max(distAC,distBC));
if (distAB==dis) return centre(A,B);
if (distAC==dis) return centre(A,C);
if (distBC==dis) return centre(B,C);
return centre(A,B);
}
//a1x+b1y+c1=0->a1a2x+a2b1y+a2c1=0
//a2x+b2y+c2=0->a1a2x+a1b2y+a1c2=0
node now;
now.y=(X.A*Y.C-X.C*Y.A)/(Y.A*X.B-X.A*Y.B);
now.x=(-X.C-X.B*now.y)/X.A;
now.r=dist(now,A); return now;
}
void solve()
{
ans=a[1]; ans.r=0;
for (int i=2; i<=n; i++)
{
if (dcmp(dist(ans,a[i])-ans.r)<=0) continue;
ans=a[i]; ans.r=0;
for (int j=1; j<i; j++)
{
if (dcmp(dist(ans,a[j])-ans.r)<=0) continue;
ans=centre(a[i],a[j]);
for (int k=1; k<j; k++)
{
if (dcmp(dist(ans,a[k])-ans.r)<=0) continue;
ans=centre(a[i],a[j],a[k]);
}
}
}
cout << fixed << setprecision(3) << ans.r;
}
int main()
{
init();
solve();
return 0;
}