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。


Sulotion

因爲只有固定的方向才能增幅,而結果爲橢圓,於是我們可以把它縮放爲增幅前的圓,
所以先旋轉a度(用三角函數要轉弧度),然後每個點橫座標除以p,最後最小圓覆蓋。
最小圓覆蓋的方法:隨機增量法 http://blog.csdn.net/commonc/article/details/52291822(非常詳細且證明了時間複雜度期望爲O(n))
及已知三點求外接圓的方法 http://blog.csdn.net/liyuanbhu/article/details/52891868

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;

#define N 50050
#define DB double
#define pi 3.1415926535897932384626433832795

struct note
{
    DB x,y;
};

note a[N];
DB al,th,p,co,si,ans,s;
int n; 

DB sqr(DB x){return x*x;}
DB dis(note x,note y){return sqrt(sqr(x.x-y.x)+sqr(x.y-y.y));}
bool pd(int x) {return dis(a[0],a[x])<=s;} 

void init()
{
    scanf("%d",&n);
    int x,y;
    for (int i=1;i<=n;i++)
    {
        scanf("%d%d",&x,&y);
        a[i].x=DB(x); a[i].y=DB(y);
    }
    scanf("%d%d",&x,&y);
    al=DB(x); p=DB(y);
    th=al*pi/180.00000;
    si=sin(th); co=cos(th);
    DB xx,yy;
    for (int i=1;i<=n;i++)
    {
        xx=a[i].x; yy=a[i].y;
        a[i].x=si*yy+co*xx;
        a[i].y=co*yy-si*xx;
        a[i].x/=p;
    }
}

note solve(note x,note y,note z)
{
    DB a,b,c,d,e,f;
    a=x.x-y.x; b=x.y-y.y; c=x.x-z.x; d=x.y-z.y;
    e=sqr(x.x)-sqr(y.x)+sqr(x.y)-sqr(y.y);  e/=2;
    f=sqr(x.x)-sqr(z.x)+sqr(x.y)-sqr(z.y);  f/=2;
    note re;
    re.x=-(d*e-b*f)/(b*c-a*d);
    re.y=-(a*f-c*e)/(b*c-a*d);
    return re;
}

void find()
{
    random_shuffle(a+1,a+n+1);
    for (int i=1;i<=n;i++)
      if (pd(i)==false)
      {
        a[0]=a[i]; s=0.0;
        for (int j=1;j<=i-1;j++)
          if (pd(j)==false)
          {
            a[0].x=(a[i].x+a[j].x)/2; a[0].y=(a[i].y+a[j].y)/2;
            s=dis(a[i],a[j])/2;
            for (int k=1;k<=j-1;k++)
              if (pd(k)==false)
              {
                a[0]=solve(a[i],a[j],a[k]);
                s=dis(a[0],a[i]);
              }
          }
      }
}

int main()
{
    freopen("amplifier.in","r",stdin);
    freopen("amplifier.out","w",stdout);
    init();
    find();
    ans=s;
    printf("%.3lf\n",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章