zoukankan      html  css  js  c++  java
  • 半平面交

    5.1  半平面交模板(from UESTC) 
     
    const double eps = 1e-8; 
    const double PI = acos(-1.0); 
    int sgn(double x) 
    { 
      if(fabs(x) < eps) return 0; 
      if(x < 0) return -1; 
      else return 1; 
    } 
    struct Point 
    { 
      double x,y; 
      Point(){} 
      Point(double _x,double _y) 
      { 
        x = _x; y = _y; 
      } 
      Point operator -(const Point &b)const 
      { 
        return Point(x - b.x, y - b.y); 
      } 
      double operator ^(const Point &b)const 
      { 
        return x*b.y - y*b.x; 
      } 
      double operator *(const Point &b)const 
      { 
        return x*b.x + y*b.y; 
      } 
    }; 
    struct Line 
    { 
      Point s,e; 
      double k; 
      Line(){} 
      Line(Point _s,Point _e) 
      { 
        s = _s; e = _e; 
        k = atan2(e.y - s.y,e.x - s.x); 
      } 
      Point operator &(const Line &b)const 
      { 
        Point res = s; 
        double t = ((s - b.s)^(b.s - b.e))/((s - e)^(b.s - b.e)); 
        res.x += (e.x - s.x)*t; 
        res.y += (e.y - s.y)*t; 
        return res; 
      } 
    }; 
    //半平面交,直线的左边代表有效区域 
    bool HPIcmp(Line a,Line b) 
    { 
      if(fabs(a.k - b.k) > eps)return a.k < b.k; 
      return ((a.s - b.s)^(b.e - b.s)) < 0; 
    } 
    Line Q[110]; 
    void HPI(Line line[], int n, Point res[], int &resn) 
    { 
      int tot = n; 
      sort(line,line+n,HPIcmp); 
      tot = 1; 
      for(int i = 1;i < n;i++) 
        if(fabs(line[i].k - line[i-1].k) > eps)
          line[tot++] = line[i]; 
      int head = 0, tail = 1; 
      Q[0] = line[0]; 
      Q[1] = line[1]; 
      resn = 0; 
      for(int i = 2; i < tot; i++) 
      { 
        if(fabs((Q[tail].e-Q[tail].s)^(Q[tail-1].e-Q[tail-1].s)) < eps || 
    fabs((Q[head].e-Q[head].s)^(Q[head+1].e-Q[head+1].s)) < eps) 
          return; 
        while(head < tail && (((Q[tail]&Q[tail-1]) - 
    line[i].s)^(line[i].e-line[i].s)) > eps) 
          tail--; 
        while(head < tail && (((Q[head]&Q[head+1]) - 
    line[i].s)^(line[i].e-line[i].s)) > eps) 
          head++; 
        Q[++tail] = line[i]; 
      } 
      while(head < tail && (((Q[tail]&Q[tail-1]) - 
    Q[head].s)^(Q[head].e-Q[head].s)) > eps) 
        tail--; 
      while(head < tail && (((Q[head]&Q[head-1]) - 
    Q[tail].s)^(Q[tail].e-Q[tail].e)) > eps) 
        head++; 
      if(tail <= head + 1)return; 
      for(int i = head; i < tail; i++) 
        res[resn++] = Q[i]&Q[i+1]; 
      if(head < tail - 1) 
        res[resn++] = Q[head]&Q[tail]; 
    } 
    5.2  普通半平面交写法 
    POJ 1750 
    const double eps = 1e-18; 
    int sgn(double x) 
    { 
      if(fabs(x) < eps)return 0; 
      if(x < 0)return -1; 
      else return 1; 
    } 
    struct Point 
    { 
      double x,y; 
      Point(){} 
      Point(double _x,double _y) 
      { 
        x = _x; y = _y; 
      } 
      Point operator -(const Point &b)const 
      { 
        return Point(x - b.x, y - b.y); 
      } 
      double operator ^(const Point &b)const 
      { 
        return x*b.y - y*b.x; 
      } 
      double operator *(const Point &b)const 
      { 
        return x*b.x + y*b.y; 
      } 
    }; 
    //计算多边形面积 
    double CalcArea(Point p[],int n) 
    { 
      double res = 0; 
      for(int i = 0;i < n;i++) 
        res += (p[i]^p[(i+1)%n]); 
      return fabs(res/2); 
    } 
    //通过两点,确定直线方程 
    void Get_equation(Point p1,Point p2,double &a,double &b,double &c) 
    { 
      a = p2.y - p1.y; 
      b = p1.x - p2.x; 
      c = p2.x*p1.y - p1.x*p2.y; 
    } 
    //求交点 
    Point Intersection(Point p1,Point p2,double a,double b,double c) 
    { 
      double u = fabs(a*p1.x + b*p1.y + c); 
      double v = fabs(a*p2.x + b*p2.y + c); 
      Point t; 
      t.x = (p1.x*v + p2.x*u)/(u+v); 
      t.y = (p1.y*v + p2.y*u)/(u+v); 
      return t; 
    } 
    Point tp[110]; 
    void Cut(double a,double b,double c,Point p[],int &cnt) 
    { 
      int tmp = 0; 
      for(int i = 1;i <= cnt;i++) 
      { 
        //当前点在左侧,逆时针的点 
        if(a*p[i].x + b*p[i].y + c < eps)tp[++tmp] = p[i]; 
        else 
        { 
          if(a*p[i-1].x + b*p[i-1].y + c < -eps) 
            tp[++tmp] = Intersection(p[i-1],p[i],a,b,c); 
          if(a*p[i+1].x + b*p[i+1].y + c < -eps) 
            tp[++tmp] = Intersection(p[i],p[i+1],a,b,c); 
        } 
      } 
      for(int i = 1;i <= tmp;i++) 
        p[i] = tp[i]; 
      p[0] = p[tmp]; 
      p[tmp+1] = p[1]; 
      cnt = tmp; 
    } 
    double V[110],U[110],W[110]; 
    int n; 
    const double INF = 100000000000.0; 
    Point p[110]; 
    bool solve(int id) 
    { 
      p[1] = Point(0,0); 
      p[2] = Point(INF,0); 
      p[3] = Point(INF,INF); 
      p[4] = Point(0,INF); 
      p[0] = p[4]; 
      p[5] = p[1]; 
      int cnt = 4; 
      for(int i = 0;i < n;i++) 
        if(i != id) 
        { 
          double a = (V[i] - V[id])/(V[i]*V[id]); 
          double b = (U[i] - U[id])/(U[i]*U[id]); 
          double c = (W[i] - W[id])/(W[i]*W[id]); 
          if(sgn(a) == 0 && sgn(b) == 0) 
          { 
            if(sgn(c) >= 0)return false; 
            else continue; 
          } 
          Cut(a,b,c,p,cnt); 
        } 
      if(sgn(CalcArea(p,cnt)) == 0)return false; 
      else return true; 
    } 
    int main() 
    { 
        while(scanf("%d",&n) == 1) 
      { 
        for(int i = 0;i < n;i++) 
          scanf("%lf%lf%lf",&V[i],&U[i],&W[i]); 
        for(int i = 0;i < n;i++) 
        { 
          if(solve(i))printf("Yes
    "); 
          else printf("No
    "); 
        } 
      } 
        return 0; 
    } 
    

      

  • 相关阅读:
    SpringSecurity配置
    SpringBoot整合Mybatis
    springboot整合JDBC
    SpringBoot的WEB流程
    List&TreeSet实现斗地主发牌及牌序
    SpringBoot第一个程序
    项目错误总结2021.4.21
    Spring整合Mybatis
    学习——构建民航业知识图谱并实现语义查询的
    新闻文本分类——词云可视化
  • 原文地址:https://www.cnblogs.com/xzxl/p/7247665.html
Copyright © 2011-2022 走看看