zoukankan      html  css  js  c++  java
  • BZOJ4107 : [Wf2015]Asteroids

    首先将速度相减,变成A在动而B不动,若速度为0则显然永远不会相交。

    枚举A的每个点以及B的每条线段,计算这三个点共线的时刻。

    将时刻排序,对于每个区间进行三分,用半平面交计算相交面积。

    注意特判相交面积为0但是存在交点的情况。

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

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int N=200;
    const double eps=1e-9;
    int sgn(double x){
      if(x<-eps)return -1;
      if(x>eps)return 1;
      return 0;
    }
    int n,m,cnt,i,j,vx,vy,x,y;double q[N],ans=-1,anst;
    struct vec{
      double x,y;
      vec(){x=y=0;}
      vec(double _x,double _y){x=_x,y=_y;}
      vec operator+(vec v){return vec(x+v.x,y+v.y);}
      vec operator-(vec v){return vec(x-v.x,y-v.y);}
      vec operator*(double v){return vec(x*v,y*v);}
      vec operator/(double v){return vec(x/v,y/v);}
      double operator*(vec v){return x*v.x+y*v.y;}
      double len(){return hypot(x,y);}
      double len_sqr(){return x*x+y*y;}
    }a[N],b[N],c[N],v,o;
    double cross(vec a,vec b){return a.x*b.y-a.y*b.x;}
    bool point_on_segment(vec p,vec a,vec b){
      return sgn(cross(b-a,p-a))==0&&sgn((p-a)*(p-b))<=0;
    }
    int has_intersection(vec a,vec b,vec p,vec q){
      int d1=sgn(cross(b-a,p-a)),d2=sgn(cross(b-a,q-a)),
          d3=sgn(cross(q-p,a-p)),d4=sgn(cross(q-p,b-p));
      if(d1*d2<0&&d3*d4<0)return 1;
      if(d1==0&&point_on_segment(p,a,b))return -1;
      if(d2==0&&point_on_segment(q,a,b))return -1;
      if(d3==0&&point_on_segment(a,p,q))return -1;
      if(d4==0&&point_on_segment(b,p,q))return -1;
      return 0;
    }
    int line_intersection(vec a,vec b,vec p,vec q,vec&o){
      double U=cross(p-a,q-p),D=cross(b-a,q-p);
      if(sgn(D)==0)return 0;
      o=a+(b-a)*(U/D);
      return 1;
    }
    struct P{
      double x,y;
      P(){x=y=0;}
      P(double _x,double _y){x=_x,y=_y;}
      P(vec p){x=p.x,y=p.y;}
      P operator-(const P&a)const{return P(x-a.x,y-a.y);}
      P operator+(const P&a)const{return P(x+a.x,y+a.y);}
      P operator*(double a)const{return P(x*a,y*a);}
    };
    namespace Halfplane{
    P p[N],a[N];
    struct L{
      P p,v;double a;
      L(){}
      L(P _p,P _v){p=_p,v=_v;}
      bool operator<(const L&b)const{return a<b.a;}
      void cal(){a=atan2(v.y,v.x);}
    }line[N],q[N];
    int cl;
    double cross(const P&a,const P&b){return a.x*b.y-a.y*b.x;}
    void newL(const P&a,const P&b){line[++cl]=L(a,b-a);}
    bool left(const P&p,const L&l){return cross(l.v,p-l.p)>0;}
    P pos(const L&a,const L&b){
      P x=a.p-b.p;
      double t=cross(b.v,x)/cross(a.v,b.v);
      return a.p+a.v*t;
    }
    double halfplane(){
      for(int i=1;i<=cl;i++)line[i].cal();
      sort(line+1,line+cl+1);
      int h=1,t=1;
      q[1]=line[1];
      for(int i=2;i<=cl;i++){
        while(h<t&&!left(p[t-1],line[i]))t--;
        while(h<t&&!left(p[h],line[i]))h++;
        if(fabs(cross(q[t].v,line[i].v))<eps)q[t]=left(q[t].p,line[i])?q[t]:line[i];
        else q[++t]=line[i];
        if(h<t)p[t-1]=pos(q[t],q[t-1]);
      }
      while(h<t&&!left(p[t-1],q[h]))t--;
      p[t]=pos(q[t],q[h]);
      if(t-h<=1)return -1;
      double ans=0;
      for(int i=h;i<t;i++)ans+=cross(p[i],p[i+1]);
      return ans+cross(p[t],p[h]);
    }
    }
    double cal(double T){
      if(!sgn(T))return -1;
      double ret=-1;
      int i,j;
      for(i=0;i<=n;i++)c[i]=a[i]+(v*T);
      for(i=0;i<n;i++)for(j=0;j<m;j++)if(has_intersection(c[i],c[i+1],b[j],b[j+1]))ret=0;
      Halfplane::cl=0;
      for(i=0;i<n;i++)Halfplane::newL(P(c[i+1]),P(c[i]));
      for(i=0;i<m;i++)Halfplane::newL(P(b[i+1]),P(b[i]));
      ret=max(ret,Halfplane::halfplane());
      if(sgn(ret-ans)>0||(sgn(ret-ans)==0&&T<anst))ans=ret,anst=T;
      return ret;
    }
    int main(){
      scanf("%d",&n);
      for(i=0;i<n;i++)scanf("%lf%lf",&a[i].x,&a[i].y);a[n]=a[0];
      scanf("%d%d",&vx,&vy);
      scanf("%d",&m);
      for(i=0;i<m;i++)scanf("%lf%lf",&b[i].x,&b[i].y);b[m]=b[0];
      scanf("%d%d",&x,&y);
      vx-=x,vy-=y;
      if(!vx&&!vy)return puts("never"),0;
      v=vec(vx,vy);
      q[cnt=1]=0;
      for(i=0;i<n;i++)
        for(j=0;j<m;j++)if(line_intersection(a[i],a[i]+v,b[j],b[j+1],o))
          q[++cnt]=(o-a[i]).len()/v.len();
      sort(q+1,q+cnt+1);
      for(i=1;i<=cnt;i++)cal(q[i]);
      for(i=1;i<cnt;i++){
        double l=q[i],r=q[i+1];
        while(l+1e-6<r){
          double len=(r-l)/3,m1=l+len,m2=r-len;
          double f1=cal(m1),f2=cal(m2);
          if(sgn(f1-f2)>=0)r=m2;else l=m1;
        }
      }
      if(ans<-0.5)puts("never");else printf("%.6f",anst);
      return 0;
    }
    

      

  • 相关阅读:
    默认路由
    路由与交换,cisco路由器配置,动态路由协议—RIP
    路由与交换,cisco路由器配置,浮动静态路由
    路由与交换,cisco路由器配置,静态路由
    路由与交换,cisco路由器配置,基础知识点(二)
    路由与交换,cisco路由器配置,基础知识点(一)
    Linux服务器架设篇,Nginx服务器的架设
    BIOS和DOS中断大全
    一步一个脚印
    汇编缩写大全
  • 原文地址:https://www.cnblogs.com/clrs97/p/5652032.html
Copyright © 2011-2022 走看看