zoukankan      html  css  js  c++  java
  • BZOJ1946 : [Ceoi2006]ANTENNA

    首先通过随机增量法求出最小覆盖圆,作为答案的上界。

    然后二分答案,检验的时候枚举每个点作为原点,求出其他每个点被包括在圆内的角度区间,然后扫描线即可。

    时间复杂度$O(Tn^2log n)$。

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstdlib>
    #define N 510
    using namespace std;
    const double PI=acos(-1.0),eps=1e-8;
    int n,K,i,j,k;double R,ansr,lim,l,r,mid;
    struct P{
      double x,y;
      P(){}
      P(double _x,double _y){x=_x,y=_y;}
    }a[N],O,anso;
    struct E{
      double x;int t;
      E(){}
      E(double _x,int _t){x=_x,t=_t;}
    }e[N<<2];
    inline bool cmp(const E&a,const E&b){return a.x<b.x;}
    inline double dis(const P&x,const P&y){
      return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));
    }
    inline P center(const P&x,const P&y,const P&z){
      double a1=y.x-x.x,b1=y.y-x.y,
             c1=(a1*a1+b1*b1)/2,a2=z.x-x.x,
             b2=z.y-x.y,c2=(a2*a2+b2*b2)/2,
             d=a1*b2-a2*b1;
      return P(x.x+(c1*b2-c2*b1)/d,x.y+(a1*c2-a2*c1)/d);
    }
    inline bool exist(int S,double R){
      int m=0;
      for(int i=0;i<n;i++)if(i!=S){
        if(dis(a[S],a[i])>R+R+eps)continue;
        double A=atan2(a[i].y-a[S].y,a[i].x-a[S].x),
               B=acos(dis(a[S],a[i])/(R+R));
        e[m++]=E(A-B,1);
        e[m++]=E(A+B,-1);
        e[m++]=E(A-B+PI*2,1);
        e[m++]=E(A+B+PI*2,-1);
      }
      sort(e,e+m,cmp);
      for(int i=0,ret=1;i<m;i++)if((ret+=e[i].t)==K){
        ansr=R;
        anso=P(a[S].x+cos(e[i].x)*R,a[S].y+sin(e[i].x)*R);
        return 1;
      }
      return 0;
    }
    inline bool check(double R){
      for(int i=0;i<n;i++)if(exist(i,R))return 1;
      return 0;
    }
    int main(){
      scanf("%d%d",&n,&K);
      for(i=0;i<n;i++)scanf("%lf%lf",&a[i].x,&a[i].y);
      for(i=0;i<n;i++)swap(a[rand()%n],a[i]);
      for(O=a[0],i=1;i<n;i++)if(dis(a[i],O)>R+eps)
        for(O=a[i],R=0,j=0;j<i;j++)if(dis(a[j],O)>R+eps){
          O=P((a[i].x+a[j].x)/2,(a[i].y+a[j].y)/2),R=dis(a[i],O);
          for(k=0;k<j;k++)if(dis(a[k],O)>R+eps)O=center(a[k],a[j],a[i]),R=dis(a[i],O);
        }
      lim=ansr=R,anso=O;
      r=ansr-eps;
      while(l+eps<r){
        lim/=2;
        if(lim<1e-5)break;
        mid=(l+r)/2;
        if(check(mid))r=mid-eps;else l=mid+eps;
      }
      return printf("%.6f
    %.6f %.6f",ansr,anso.x,anso.y),0;
    }
    

      

  • 相关阅读:
    【3】网站搭建:分页功能
    mapserv和mapserv.exe的区别
    WMS请求GetCapabilities,变成下载mapserv.exe解决办法
    get和post的区别
    实现ajax异步请求
    Thinkphp3.2 Widget的扩展
    Thinkphp3.2 路由是使用
    Thinkphp3.2 TagLib的使用
    Thinkphp下实现Rbac
    Thinkphp下实现分页
  • 原文地址:https://www.cnblogs.com/clrs97/p/5758892.html
Copyright © 2011-2022 走看看