zoukankan      html  css  js  c++  java
  • P2742 [USACO5.1]圈奶牛Fencing the Cows /【模板】二维凸包

    凸包模板题

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int N = 1e5+10;
    const double eps = 1e-10;//精度
    //atan2(y,x)求极角的弧度
    struct Point{
        double x,y;
        Point(double x = 0, double y = 0):x(x),y(y){}
    };//点
    typedef Point Vector;//向量
    Vector operator + (Vector A, Vector B)
    {
        return Vector{A.x + B.x,A.y + B.y };
    }
    Vector operator - (Vector A, Vector B)
    {
        return Vector{A.x - B.x,A.y - B.y };
    }
    Vector operator * (Vector A, double p)
    {
        return Vector{A.x * p ,A.y * p};
    }
    Vector operator / (Vector A,double p)
    {
        return Vector{A.x / p,A.y / p};
    }
    bool operator < (const Point& a, const Point& b)//判断位置,先按照x坐标排序然后按照y坐标排序
    {
        return a.x < b.x || (a.x == b.x && a.y < b.y);
    }
    
    int dcmp(double x)//判断x的符号
    {
        if(fabs(x) < eps)
            return 0;
        else
            return x < 0 ? -1 : 1;
    }
    bool operator == (const Point &a,const Point &b)//判断两个点是否重合
    {
        return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;
    }
    double Dot(Vector A,Vector B)//两个向量的点积
    {
        return A.x*B.x + A.y*B.y;
    }
    double Length(Vector A)//向量的长度
    {
        return sqrt(Dot(A,A));
    }
    double Angle(Vector A,Vector B)//求两个向量夹角(弧度)
    {
        return acos(Dot(A,B)/Length(A)/Length(B));
    }
    //A×B,B在A的左边是正,在右边是负
    double Cross(Vector A,Vector B)//两个向量的叉积
    {
        return A.x*B.y - A.y*B.x;
    }
    double Area2(Point A,Point B,Point C)//ABC三角形有向面积的两倍
    {
        return Cross(B-A,C-A);
    }
    Vector Rotate(Vector A,double rad)//向量逆时针旋转rad
    {
        return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
    }
    //把向量向左旋转90°,得到法向量,得保证A向量不是零向量
    Vector Normal(Vector A)
    {
        double L = Length(A);
        return Vector(-A.y/L,A.x/L);
    }
    //两条直线的交点,向量式--参数方程.前提是v,w向量不平行,Cross(v,w)!=0
    Point GetLineIntersection(Point P,Vector v,Point Q,Vector w)
    {
        Vector u = P - Q;
        double t = Cross(w,u) / Cross(v,w);//P,v直线的参数t
        return P + v*t;
    }
    //P到直线A-B距离
    double DistanceToLine(Point P, Point A, Point B)
    {
        Vector v1=B-A, v2=P-A;
        return fabs(Cross(v1,v2) / Length(v1));
    }
    //P到线段A-B距离
    //设投影点为Q,如果Q在线段AB上,则所求距离就是P点直线AB的距离,如果Q在射线BA上,则所求距离为PA距离;否则为PB距离。
    double DistanceToSegment(Point P, Point A, Point B)
    {
        if(A==B) return Length(P-A);
        Vector v1=B-A, v2=P-A, v3=P-B;
        if(dcmp(Dot(v1,v2)) < 0) return Length(v2);//PA距离
        else if(dcmp(Dot(v1,v3)) > 0) return Length(v3);//PB距离
        else return fabs(Cross(v1,v2)) / Length(v1);//PQ距离
    }
    //求P到直线A-B垂点
    Point GetLineProjection(Point P, Point A, Point B)
    {
        Vector v=B-A;
        return A+v*(Dot(v,P-A)) / Dot(v,v);
    }
    //两线是否规范相交
    bool SegmentProPerIntersection(Point a1, Point a2, Point b1,Point b2)
    {
        double c1=Cross(a2-a1,b1-a1), c2=Cross(a2-a1,b2-a1),
                c3=Cross(b2-b1,a1-b1), c4=Cross(b2-b1,a2-b1);
        return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
    }
    //p点是否在a1,a2线段上(不在a1,a2点上)
    bool OnSegment(Point p, Point a1, Point a2)
    {
        return dcmp(Cross(a1-p,a2-p))==0 && dcmp(Dot(a1-p,a2-p)) < 0;
    }
    //判断多边形的面积(凸,非凸都行)
    double PolygomArea(Point *p, int n)
    {
        double area = 0;
        for(int i=1;i<n;i++)
        {
            area += Cross(p[i]-p[0],p[i+1]-p[0]);
        }
        return area/2;
    }
    //Andrew算法求凸包
    int ConvexHull(Point *p,int n,Point *ch)
    {
        sort(p,p+n);
        int m = 0;
        for(int i=0;i<n;i++)
        {
            while(m > 1 && Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]) <= 0)
                m--;
            ch[m++] = p[i];
        }
        int k = m;
        for(int i=n-2;i>=0;i--)
        {
            while(m > k && Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]) <= 0)
                m--;
            ch[m++] = p[i];
        }
        if(m > 1)
            m--;
        return m;
    }
    Point p[N],ch[N];
    void solve()
    {
        int n;
        cin >> n;
        for(int i=0;i<n;i++)
        {
            cin >> p[i].x >> p[i].y;
        }
        int m = ConvexHull(p,n,ch);
        double ans = 0;
        for(int i=1;i<=m;i++)
        {
            ans += Length(ch[i]-ch[i-1]);
        }
        printf("%0.2lf
    ",ans);
    }
    int main()
    {
        int T = 1;
        while(T--)
        {
            solve();
        }
        return 0;
    }
    
    
  • 相关阅读:
    某耳机厂商微信公众平台建设方案
    微信公众号订单好评红包返现系统
    LNMP的配置与优化
    微信公众号用户OpenID同步导出系统
    微信公众号无限定时群发系统
    小程序想要什么
    微信支付默认推荐关注规则
    微信小程序(应用号)资源汇总整理
    微信公众平台小程序开发教程
    微信应用号开发教程
  • 原文地址:https://www.cnblogs.com/hh13579/p/13762932.html
Copyright © 2011-2022 走看看