凸包模板!!

本文介绍了一个基于水平序的凸包算法实现,通过Graham扫描法找出二维平面上一系列点构成的凸包边界,并计算其周长。代码中定义了点结构体及用于比较和交叉乘计算的函数,实现了完整的Graham扫描过程。
#include<map>
#include<set>
#include<list>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cctype>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 1005
#define INF 0x3f3f3f3f
#define LL long long
#define DBL double
#define eps 1e-6
#define PI acos(-1.0)
#define Test() cout<<"Test"<<endl;
#define Debug(a) cout<<#a<<" = "<<a<<endl;
#define Debug2(a,b) cout<<#a<<" = "<<a<<" , "<<#b<<" = "<<b<<endl;
using namespace std;

struct P{
    DBL x, y;
};
int n, L;
P p[MAXN];

bool cmp(P a, P b){
    return a.y<b.y || (a.y==b.y && a.x<b.x);
}
DBL mul(DBL t){
    return t*t;
}
DBL dis(P a, P b){
    return sqrt(mul(a.x-b.x)+mul(a.y-b.y));
}
int dblcmp(DBL x){
    return fabs(x)<eps? 0: x>0? 1: -1;
}
DBL cross(P a, P b, P c){        //ab X ac
    return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
DBL grahamScan(){                //水平序 
    sort(p, p+n, cmp);
    int top=-1, s[MAXN], tmp;
    s[++top]=0, s[++top]=1; 
    for(int i=2; i<n; i++){        // 做右链
        while(top>0 && dblcmp(cross(p[s[top-1]], p[s[top]], p[i])) <= 0) top --;
        s[++top] = i;
    }
    tmp = top;                    // 此时的栈顶元素一定是第n个点
    s[++top]=n-2;
    for(int i=n-3; i>=0; i--){    // 做左链
        while(top>tmp && dblcmp(cross(p[s[top-1]], p[s[top]], p[i])) <= 0) top --;
        s[++top] = i;
    }                            // 此时的栈顶元素一定是第1个点,即s[top]=s[0]
    // s[0~top-1]即为所求凸包 
    DBL res=0;
    for(int i=0; i<top; i++)
        res += dis(p[s[i]], p[s[i+1]]);
    return res+2*PI*L;
}

int main(){
    while(cin >> n >> L){
        for(int i=0; i<n; i++)
            scanf("%lf%lf", &p[i].x, &p[i].y);
        printf("%d\n", (int)(grahamScan()+0.5));      //+0.5      
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值