zoukankan      html  css  js  c++  java
  • 凸包

    前置知识

    极角排序:按向量与(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;
    }
    
    
  • 相关阅读:
    sublime
    C++两种字符串传参构造函数
    Navicat 导入Excel与增加主键
    5,做一个用户登录之后查看学员信息的小例子
    4,Flask 中的 request
    3,Flask 中的模板语言 Jinja2 及 render_template 的深度用法
    2,Flask 中的 Render Redirect HttpResponse
    1,flask简介
    11,手动绘制散点图的背景颜色
    10,knn手写数字识别
  • 原文地址:https://www.cnblogs.com/redegg/p/11980463.html
Copyright © 2011-2022 走看看