凸包

前置知识

极角排序:按向量与(x)轴的极角排序,( hetain [0,2pi])

向量差集:(vec a imesvec b=x_ay_b-x_by_a),可以发现极角排序中若(vec alt vec b,vec a imes vec bgt 0)

凸包

先找到所有点中最下面的点,多个最下面则取最左边。

然后按照这个点为原点(O),对其它点(P)的向量(overrightarrow {OP})极角排序。排序后呈现类似扇形顺序。

然后每次按顺序丢入点(p_i)(p_i)和凸包内前一个点形成的向量(overrightarrow {p_ip_{i-1}}),若(overrightarrow {p_ip_{i-1}} imes overrightarrow {p_{i-1}p_{i-2}}>0),说明(p_{i-1})成凹陷进去的一个顶点了,于是把(p_{i-1})删除。依次这样添加即可。

模板题:P2742

#include <bits/stdc++.h>
using namespace std;

const double eps=1e-8;
const double pi = acos(-1.0);
const int MAXN=10005;

int n,cnt;


struct vec {
    double x=0.0,y=0.0;
    int id=0;
    vec(double X=0,double Y=0,int ID=0){
        x=X,y=Y,id=ID;
    }
}p[MAXN],o,ax[MAXN];//Point : X (x,y) , O (x,y) ; Vector :  AX_id (x,y)

vec operator + (vec aa,vec bb){ return (vec){aa.x+bb.x, aa.x+bb.y,0}; }
vec operator - (const vec &aa,const vec &bb){return (vec){aa.x-bb.x,aa.y-bb.y,0};}
double operator * (const vec &aa,const vec &bb){return aa.x*bb.x+aa.y*bb.y;}
double operator ^ (const vec &aa,const vec &bb){return aa.x*bb.y-aa.y*bb.x;}
vec operator * (const double bb,const vec &aa){return (vec){bb*aa.x,bb*aa.y,aa.id};}
vec rotate (vec aa,double bb){
    return (vec){cos(bb)*aa.x-sin(bb)*aa.y,sin(bb)*aa.x+cos(bb)*aa.y,aa.id};
}
double dis(const vec &aa){
    return sqrt(aa.x*aa.x+aa.y*aa.y);
}

bool cmp (const vec &aa,const vec &bb){//Sort the vector AX_i
    if(fabs(aa^bb) > eps)return (aa^bb) > eps;
    else {
        return fabs(aa.x)<fabs(bb.x);
    }
}

stack <vec> st;
stack <vec> pt;

int main(){

    o.x=1e17,o.y=1e17;

    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lf%lf",&p[i].x,&p[i].y);
        p[i].id=i;
        if(p[i].y<o.y-eps)o.y=p[i].y,o.x=p[i].x,o.id=i;
        if(fabs(p[i].y-o.y)<=eps&&p[i].x<o.x)o.y=p[i].y,o.x=p[i].x,o.id=i;
    }

    for(int i=1;i<=n;i++){
        if(i==o.id)continue;
        cnt++;
        ax[cnt]=p[i]-p[o.id];
        ax[cnt].id=i;
    }

    sort(ax+1,ax+1+cnt,cmp);

    st.push(p[ax[1].id]-p[o.id]);
    pt.push(p[o.id]);pt.push(p[ax[1].id]);

    for(int i=2;i<=cnt;i++){

        while(!st.empty()&&((p[ax[i].id]-pt.top())^(st.top()))>=-eps)
            st.pop(),pt.pop();
        
        st.push(p[ax[i].id]-pt.top());
        pt.push(p[ax[i].id]);
    }
    double ans=0.0;
    while(!st.empty()){
        ans+=dis(st.top());
        st.pop();
    }
    ans+=dis((vec){pt.top()-p[o.id]});

    printf("%.2f
",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/redegg/p/11980463.html