zoukankan      html  css  js  c++  java
  • POJ 1755 Triathlon

    http://poj.org/problem?id=1755

    题意:铁人三项,每个人有自己在每一段的速度,求有没有一种3条路线长度都不为0的设计使得某个人能严格获胜?

    我们枚举每个人获胜,得到不等式组:s1/v1+s2/v2+s3/v3<s1/v1'+s2/v2'+s3/v3' 是三维半平面交?接着看

    我们令两边同时除以s3得到

    (s1/s3)*(1/v1)+(s2/s3)*(1/v2)+(1/v3)<(s1/s3)*(1/v1')+(s2/s3)*(1/v2')+(1/v3')

    这样s1/s3和s2/s3就变成了唯二的变量了,这样不等式组就变成了二元一次不等式组了,用半平面交就可以解决了。

    注意有些地方:

    eps要设置到1e-16

    如果一个人有2个速度和另一个人相等,直接特判掉第三个,不建直线。

    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    const double eps=1e-16;
    const double inf=99999999;
    struct Point{
     double x,y;
     Point(){}
     Point(double x0,double y0):x(x0),y(y0){}
    }p[200005];
    struct Line{
     Point s,e;
     double slop;
     Line(){}
     Line(Point s0,Point e0):s(s0),e(e0){}
    }l[200005],c[200005];
    int tot,n,v1[200005],v2[200005],v3[200005],num[200005];
    int sgn(double x){
     if (x>eps) return 1;
     if (x<-eps) return -1;
     return 0;
    }
    int read(){
     int t=0,f=1;char ch=getchar();
     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
     return t*f;
    }
    double operator *(Point p1,Point p2){
     return p1.x*p2.y-p1.y*p2.x;
    }
    Point operator -(Point p1,Point p2){
     return Point(p1.x-p2.x,p1.y-p2.y);
    }
    bool pd(int id){
     for (int i=1;i<=n;i++)
      if (i!=id)
     {
      int cnt=0,ans1=0,ans2=0;
      if (v1[i]==v1[id]) cnt++;
      else ans1=v1[id],ans2=v1[i];
      if (v2[i]==v2[id]) cnt++;
      else ans1=v2[id],ans2=v2[i];
      if (v3[i]==v3[id]) cnt++;
      else ans1=v3[id],ans2=v3[i];
      if (cnt==3) return 0;
      else if (cnt==2){
       if (ans1<=ans2) return 0;
      }
      num[i]=cnt;
     }
     return 1;
    }
    void build(int id){
        tot=0;
        l[++tot].s=Point(0,inf);l[tot].e=Point(0,0);
        l[++tot].s=Point(0,0);l[tot].e=Point(inf,0);
        l[++tot].s=Point(inf,0);l[tot].e=Point(0,inf);
        for (int i=1;i<=n;i++)
         if (i!=id){
         if (num[i]==2) continue;
         tot++;
         double A=((double)v1[i]-v1[id])/((double)v1[id]*v1[i]); 
         double B=((double)v2[i]-v2[id])/((double)v2[id]*v2[i]);
         double C=((double)v3[i]-v3[id])/((double)v3[id]*v3[i]);
         int a=sgn(A),b=sgn(B),c=sgn(C);
         if (a==0){
          l[tot].s.x=-1;l[tot].s.y=(-C)/B;
          l[tot].e.x=1;l[tot].e.y=(-C)/B;
          if (b>0) std::swap(l[tot].s,l[tot].e);
         }else if (b==0){
          l[tot].s=Point((-C)/A,-1);
          l[tot].e=Point((-C)/A,1);
          if (a<0) std::swap(l[tot].s,l[tot].e);
         }else{
          l[tot].s=Point(-1,-((-1)*A+C)/B);
          l[tot].e=Point(1,-(A+C)/B);
          if (b>0) std::swap(l[tot].s,l[tot].e);
         }
     }
     for (int i=1;i<=tot;i++)
      l[i].slop=atan2(l[i].e.y-l[i].s.y,l[i].e.x-l[i].s.x);
    }
    Point inter(Line p1,Line p2){
     double k1=(p2.e-p1.s)*(p1.e-p1.s);
     double k2=(p1.e-p1.s)*(p2.s-p1.s);
     double t=(k2)/(k1+k2);
     double x=p2.s.x+(p2.e.x-p2.s.x)*t;
     double y=p2.s.y+(p2.e.y-p2.s.y)*t;
     return Point(x,y);
    }
    bool jud(Line p1,Line p2,Line p3){
     Point p=inter(p1,p2);
     return (p-p3.s)*(p3.e-p3.s)>=eps;
    }
    bool cmp(Line p1,Line p2){
     if (fabs(p1.slop-p2.slop)<=eps) return (p1.e-p1.s)*(p2.e-p1.s)<=0; 
     else return p1.slop<p2.slop;
    }
    bool phi(){
       int cnt=1;
       std::sort(l+1,l+1+tot,cmp);
       for (int i=2;i<=tot;i++)
        if (fabs(l[i].slop-l[i-1].slop)>eps) l[++cnt]=l[i];
       int L=1,R=2;c[1]=l[1];c[2]=l[2];
       for (int i=3;i<=cnt;i++){
        while (L<R&&jud(c[R],c[R-1],l[i])) R--;
        while (L<R&&jud(c[L],c[L+1],l[i])) L++;
        c[++R]=l[i];
       } 
       while (L<R&&jud(c[R],c[R-1],c[L])) R--;
       while (L<R&&jud(c[L],c[L+1],c[R])) L++;
       if (R-L+1<3) return 0;
       c[R+1]=c[L];
       cnt=0;
       for (int i=L;i<=R;i++)
        p[++cnt]=inter(c[i],c[i+1]);
       p[cnt+1]=p[1];
       double res=0;
       for (int i=1;i<=cnt;i++)
        res+=p[i]*p[i+1];
       res/=2.0;
       res=fabs(res);
       if (res<=eps) return 0;
       else return 1;  
    }
    bool work(int id){
       build(id);
       if (phi()) return 1;
       else return 0;
    }
    int main(){
       n=read();
       for (int i=1;i<=n;i++){
        v1[i]=read(),v2[i]=read(),v3[i]=read();
       }
       for (int i=1;i<=n;i++){
        if (pd(i)&&work(i)) puts("Yes");
        else puts("No");
       }
       return 0;
    }
  • 相关阅读:
    python 操作 mysql 数据库 datetime 属性字段为 0000-00-00 00:00:00 的问题
    git 学习笔记
    SB Admin 2 学习笔记1
    docker容器与容器云读书笔记1
    urlencode遇到中文编码问题
    flask_sqlalchemy 乱码问题
    centos6u3 安装 celery 总结
    flask_sqlalchemy 命名遇到的一个小坑
    使用 bash 创建定时任务
    tornado 异步调用系统命令和非阻塞线程池
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5660411.html
Copyright © 2011-2022 走看看