码迷,mamicode.com
首页 > 其他好文 > 详细

P2742 【模板】二维凸包 / [USACO5.1]圈奶牛Fencing the Cows

时间:2018-08-14 15:43:17      阅读:164      评论:0      收藏:0      [点我收藏+]

标签:code   mes   二维   方向   min   scan   for   iostream   span   

题意: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;
}

 

P2742 【模板】二维凸包 / [USACO5.1]圈奶牛Fencing the Cows

标签:code   mes   二维   方向   min   scan   for   iostream   span   

原文地址:https://www.cnblogs.com/olinr/p/9474825.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!