zoukankan      html  css  js  c++  java
  • hdu 1392凸包周长

    //用的自己的计算几何模板,不过比较慢嘿嘿
    //要注意只有一个点和两个点
    //Computational Geometry
    //by kevin_samuel(fenice) Soochow University
    //temple
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    #include <cstdio>
    //#include <stack>
    
    using namespace std;
    
    //define
    const double EPS = 1e-8;
    const double PI = acos(-1.0);
    
    
    
    //point
    //====================================================================
    class Point
    {
    public:
      double x;
      double y;
      Point(){}
      Point(double x,double y):x(x),y(y){}
     
      //operator
      //operator=
      Point& operator=(const Point& _P)
      {
        x = _P.x;
        y = _P.y;
        return *this;
      }
      //operator*
      double operator*(const Point& _P)const
      {
        return x*_P.y - y *_P.x;
      }
      //operator-
      Point operator-(const Point& _P)const
      {
        return Point(x - _P.x,y - _P.y);
      }
      //operator==
      bool operator==(const Point& _P)const
      {
        if(fabs(_P.x - x) < EPS && fabs(_P.y - y) < EPS)
          return true;
        else
          return false;
      }
      bool operator!=(const Point& _P)const
      {
        return ((*this) == _P) == false;
      }
      
      //dot product
      static double dotProduct(Point s1,Point e1,Point s2,Point e2)
      {
        double result = 0;
        double x1 = e1.x - s1.x;
        double y1 = e1.y - s1.y;
        double x2 = e2.x - s2.x;
        double y2 = e2.y - s2.y;
        
        result = x1*x2 + y1*y2;
        return result;
      }
    
      //cross product 1 (4 point-type params)
      static double crossProduct(Point s1,Point e1,Point s2,Point e2)
      {
        double result = 0;
        double x1 = e1.x - s1.x;
        double y1 = e1.y - s1.y;
        double x2 = e2.x - s2.x;
        double y2 = e2.y - s2.y;
        
        result = x1*y2 - x2*y1;
    
        return result;
      }
      
      //cross product 2 (3 point-type params) 
      static double crossProduct(Point p1,Point p2,Point p0)
      {
        return crossProduct(p0,p1,p0,p2);
      }
      
      //Is on segment or line
      static bool onSegment(Point Pi,Point Pj,Point Q)
      {
        if(Q.x >= min(Pi.x,Pj.x) && Q.x <= max(Pi.x,Pj.x) &&
           Q.y >= min(Pi.y,Pj.y) && Q.y <= max(Pi.y,Pj.y) &&
           fabs(crossProduct(Q,Pj,Pi)) < EPS
         )
          return true;
        else
          return false;
      }
      
      //Is on segment
      bool IsOnSegment(Point Pi,Point Pj)
      {
        if(this->x >= min(Pi.x,Pj.x) && this->x <= max(Pi.x,Pj.x) &&
           this->y >= min(Pi.y,Pj.y) && this->y <= max(Pi.y,Pj.y) &&
           fabs(Point::crossProduct(*this,Pj,Pi)) < EPS
         )
          return true;
        else
          return false;
      }
      
      //Is inside triangle
      bool inTriangle(Point A,Point B,Point C)
      {
        
        double Sabc = fabs(Point::crossProduct(B,C,A));
        double Spab = fabs(Point::crossProduct(A,B,(*this)));
        double Spac = fabs(Point::crossProduct(A,C,(*this)));
        double Spbc = fabs(Point::crossProduct(B,C,(*this)));
        
        if(Spbc + Spab + Spac == Sabc)
          return true;
        else
          return false;
      }
      
      //Is inside polygon
      //polys[] ,0-n
      bool insidePolygon(Point *polys,int n)
      {
        int counter = 0;
        double xinters;
        Point p1,p2;
        p1 = polys[0];
        for(int i = 1; i < n; i++)
          {
    	p2 = polys[i % n];
    	if(Point::onSegment(p1,p2,(*this)) == true)
    	  return true;
    	if((*this).y > min(p1.y,p2.y) && (*this).y <= max(p1.y,p2.y))
    	  {
    	    if((*this).x <= max(p1.x,p2.x) && p1.y != p2.y)
    	      {
    		xinters = ((*this).y - p1.y)*(p2.x - p1.x)/(p2.y - p1.y) + p1.x;
    		if(p1.x == p2.x || (*this).x <= xinters)
    		  counter++;
    	      }
    	  }
    	p1 = p2;
          }
        if(counter % 2 == 0)
          return false;
        return true;
      }
      
      //distance^2
      double dis2(const Point& _P)const
      {
        return (x - _P.x)*(x - _P.x) + (y - _P.y)*(y - _P.y);
      }
      //distance 
      double dis(const Point& _P)const
      {
        return sqrt(dis2(_P));
      }
        static double dis(const Point& p1,const Point& p2)
        {
            return sqrt((p2.x - p1.x)*(p2.x - p1.x) + (p2.y - p1.y)*(p2.y -p1.y));
        }
        
    };
    
    //==================================================================================
    
    //vector segment or line
    //==================================================================================
    
    class Vector
    {
    public:
      Point start;
      Point end;
      double _x;
      double _y;
      double a,b,c;        //ax + by + c = 0
      
    
      Vector(){}
      Vector(double __x,double __y):_x(__x),_y(__y){}
      Vector(Point a,Point b):start(a),end(b) { _x = end.x - start.x; _y = end.y - start.y; }
    
      //operator
      //judge the position of the point relative to the segment
      double operator*(const Point& _P)const
      {
        double res = Point::crossProduct(_P,this->end,this->start);
        if(fabs(res) < EPS)
          return 0;
        if(res > 0)
          return 1;
        else
          return -1;
      }
      
      //crossProduct
      double operator*(const Vector& _V)const
      {
        Point st = _V.start;
        Point en = _V.end;
        return Point::crossProduct(start,end,st,en);
      }
      
      //transfer to normal rex
      bool pton()
      {
        a = start.y - end.y;
        b = end.x - start.x;
        c = start.x * end.y - start.y * end.x;
        return true;
      }
    
      //judge whether _P is on the line
      bool IsLinehasPoint(const Point& _P)const
      {
        if(fabs((*this)*_P) < EPS)
          return true;
        else
          return false;
      }
      
      //juegde whether _P is on the segment
      bool IsSegmenthasPoint(const Point& _P)const
      {
        if(_P.x >= min(this->start.x,this->end.x) && _P.x <= max(this->start.x,this->end.x) &&
           _P.y >= min(this->start.y,this->end.y) && _P.y <= max(this->start.y,this->end.y) &&
           fabs((*this)*_P) < EPS
        )
          return true;
        else
          return false;
      }
    
      //the distance from point to line
      double disToPoint(const Point& _P)
      {
        pton();  //transfer
        
        double td = (a*_P.x + b*_P.y + c)/sqrt(a*a + b*b);
        
        double xp = (b*b*_P.x - a*b*_P.y -a*c)/(a*a + b*b);
        double yp = (-a*b*_P.x + a*a*_P.y - b*c)/(a*a + b*b);
        double xb = max(start.x,end.x);
        double yb = max(start.y,end.y);
        double xs = start.x + end.x - xb;
        double ys = start.y + end.y - yb;
        
        if(xp > xb + EPS||xp < xs - EPS||yp > yb + EPS||yp < ys - EPS)
          td = min(_P.dis(start),_P.dis(end));
        
        return fabs(td);
      }
    
      //out the mirror point by this line or segment
      Point mirrorPoint(const Point& _P)const
      {
        Point ret;
        
        double d = a * a + b * b;
        ret.x = (b*b*_P.x - a*a*_P.x - 2*a*b*_P.y - 2*a*c)/d;
        ret.y = (a*a*_P.y - b*b*_P.y - 2*a*b*_P.x - 2*b*c)/d;
        
        return ret;
      }
      
      //out the vertical line of two points
      static Vector verticalLine(const Point& _a,const Point& _b)
      {
        Vector ret;
        ret.start.x = (_a.x + _b.x)/2;
        ret.start.y = (_a.y + _b.y)/2;
        
        ret.a = _b.x - _a.x;
        ret.b = _b.y - _a.y;
        ret.c = (_a.y - _b.y)*ret.start.y + (_a.x - _b.x)*ret.start.x;
        
        if(fabs(ret.a) > EPS)
          {
              ret.end.y = 0.0;
              ret.end.x = -ret.c/ret.a;
              if(ret.end == ret.start)
              {
                  ret.end.y = 1e10;
                  ret.end.x = -(ret.c - ret.b * ret.end.y)/ret.a;
              }
          }
        else
          {
              ret.end.x = 0.0;
              ret.end.y = - ret.c/ret.b;
              if(ret.end == ret.start)
              {
                  ret.end.x = 1e10;
                  ret.end.y = - (ret.c - ret.a*ret.end.x)/ret.b;
              }
          }
        return ret;
      }
      
      //line with line
      //two lines coincide
      bool equal(const Vector& _P)const
      {
        return IsLinehasPoint(_P.start) && IsLinehasPoint(_P.end);
      }
    
      // two parallel lines
      bool parallel(const Vector& _P)const
      {
        return (fabs((*this)*_P)) < EPS;
      }
    
      //the intersection points of two lines
      Point Intersection(Vector _V)
      {
        //judge parallel and coincide
        Point ret = start;
        double t = ((start.x - _V.start.x)*(_V.start.y - _V.end.y) - (start.y - _V.start.y)*(_V.start.x - _V.end.x))/
          ((start.x - end.x)*(_V.start.y - _V.end.y) - (start.y - end.y)*(_V.start.x - _V.end.x));
    
        ret.x += (end.x - start.x)*t;
        ret.y += (end.y - start.y)*t;
        return ret;
      }
      
    
      //line and segment
      //is line cross with segment
      //param:segment
      bool crossSL(const Vector& _V)const
      {
        double rs = (*this)*_V.start;
        double re = (*this)*_V.end;
        return rs*re < EPS;
      }
    
      //segment and segment
      //judge wheather two segments intersect
      bool IsCrossSS(const Vector& _V)const
      {
        return (
    	    max(start.x,end.x) >= min(_V.start.x,_V.end.x) &&
    	    max(_V.start.x,_V.end.x) >= min(start.x,end.x) &&
    	    max(start.y,end.y) >= min(_V.start.y,_V.end.y) &&
    	    max(_V.start.y,_V.end.y) >= min(start.y,end.y) &&
    	    ((Vector(_V.start,start)*_V)*(_V*Vector(_V.start,end)) >= EPS) &&
    	    ((Vector(start,_V.start)*(*this))*((*this)*Vector(start,_V.start))>=EPS)
    
    	    );
      }
      
      
    };
    //=================================================================================
    //Graham-scan
    #define MAXN 110
    Point Points[MAXN];
    
    int N;
    
    int stack[MAXN];
    int top;
    
    bool cmp(const Point& a,const Point& b)
    {
      if(a.y == b.y)
        return a.x < b.x;
      else
        return a.y < b.y;
    }
    
    bool multi(Point sp,Point ep,Point op)
    {
        return (sp.x - op.x)*(ep.y - op.y) >= (ep.x - op.x)*(sp.y - op.y);
    }
    
    void Graham_Scan()
    {
        int len;
        top = 1;
        sort(Points,Points+N,cmp);
        if(N == 0)
            return;
        stack[0] = 0;
        if(N == 1)
            return;
        stack[1] = 1;
        if(N == 2)
            return;
        stack[2] = 2;
        for(int i = 2; i < N; i++)
        {
            while(top && multi(Points[i],Points[stack[top]],Points[stack[top-1]])) top--;
            stack[++top] = i;
        }
        len = top;
        stack[++top] = N - 2;
        for(int i = N - 3; i >= 0; i--)
        {
            while(top != len && multi(Points[i],Points[stack[top]],Points[stack[top-1]])) top--;
            stack[++top] = i;
        }
    }
    //==================================================================================
    //test zone
    
    int main()
    {
        while(cin>>N)
        {
            if(N == 0)
                break;
            for(int i = 0; i < N; i++)
            {
                cin>>Points[i].x>>Points[i].y;
            }
            Graham_Scan();
            double length = 0;
            for(int i = 0; i <= top - 2; i++)
            {
                length +=Point::dis(Points[stack[i]],Points[stack[i+1]]);
            }
            length +=Point::dis(Points[stack[top - 1]],Points[stack[0]]);
            if(N == 1)
                printf("0.00
    ");
            else if(N == 2)
                printf("%.2lf
    ",Point::dis(Points[0],Points[1]));
            else
                printf("%.2lf
    ",length);
        }
      return 0;
    }
    


  • 相关阅读:
    游戏方案
    团队介绍
    【面向对象程序设计】作业四
    FIFO与LRU实现(Java)
    spring事务介绍
    微信抢红包算法
    Hibernate Dao映射配置通用接口类反射获取加载calass实例
    股票两次买卖最大收益(java)
    Eclipse安装JD-Eclipse反编译插件看源码
    Java GC调优
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3235352.html
Copyright © 2011-2022 走看看