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

    题意:n个点,求凸包周长。(纯板子QAQ)

    定义

    凸包:用最小的凸多边形将n个点围在里面的图形为凸包

    前置

    向量:点积:(a,b) (c,d)=(a*c,b*d) =|(a,b)|*|(c,d)|*cos<(a,b),(c,d)>;

               叉积:(a,b) (c,d)=a*d-b*c=|(a,b)|*|(c,d)|*sin<(a,b),(c,d)>;

          几何意义:以(a,b)(c,d)两向量作平行四边形,它俩的叉积为其面积

              故有三角形面积=$large{frac{1}{2}*|(a,b)|*|(c,d)|*sin<(a,b),(c,d)>}$

    极角:与x轴的夹角,STL库有atan2函数,atan2(y,x)求出向量(x,y)的极角

    算法

    1、找到最左下的点,以其为原点建立平面直角坐标系

    2、求出各点新坐标以及极角

    3、以极角为关键字从小到大排序

    4、前三个点入栈

    5、用叉积判方向看当前栈顶应不应该留下,留下则当前点入栈,否则一直弹(直到能够留下)

    6、第5步后,栈中元素即为所需点,相邻两个作差求模长,累计即为答案

    #include<algorithm>
    #include<cstdio>
    #include<iostream>
    #include<cmath>
    using namespace std;
    #define olinr return
    #define love_nmr 0
    struct node
    {
        double x,y,jj;
        node():x(0),y(0),jj(0){}
        friend node operator - (const node &a,const node &b)
        {
            node c;
            c.x=a.x-b.x;
            c.y=a.y-b.y;
            olinr c;
        }
        friend double operator ^ (const node &a,const node &b)
        {
            olinr a.x*b.y-a.y*b.x;
        }
        double mo()
        {
            olinr sqrt(x*x+y*y);
        }
        friend bool operator < (const node &a,const node &b)
        {
            olinr a.jj<b.jj;
        }
    }cow[10505];
    int n;
    double ans;
    int s[20505];
    int top;
    int minn=1;
    inline void swap(node &x,node &y)
    {
        node t=x; x=y; y=t;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%lf%lf",&cow[i].x,&cow[i].y);
            if((cow[i].y<cow[minn].y)||((cow[i].y==cow[minn].y)&&(cow[i].x<cow[minn].x))) minn=i;
        }
        swap(cow[1],cow[minn]);
        for(int i=2;i<=n;i++)
        {
            cow[i].x-=cow[1].x;
            cow[i].y-=cow[1].y;
            cow[i].jj=atan2(cow[i].y,cow[i].x);
        }
        cow[1].x=0;
        cow[1].y=0;
        sort(cow+2,cow+1+n);
        s[1]=1;
        s[2]=2;
        s[3]=3;
        top=3;
        for(int i=4;i<=n;i++)
        {
            while(top>2&&((cow[s[top]]-cow[s[top-1]])^(cow[i]-cow[s[top]]))<0)
                top--;
            s[++top]=i;
        }
        for(int i=1;i<top;i++)
            ans+=(cow[s[i+1]]-cow[s[i]]).mo();
        ans+=(cow[n]-cow[1]).mo();
        printf("%.2lf",ans);
        olinr love_nmr;
    }
  • 相关阅读:
    不死神兔
    C/C++内存管理详解
    python下调用不在环境变量中的firefox
    【转至nmap】nc命令
    Linux SSH隧道技术(端口转发,socket代理)
    linux共享上网设置
    HDU
    CSU
    HDU
    HDU
  • 原文地址:https://www.cnblogs.com/olinr/p/9474825.html
Copyright © 2011-2022 走看看