#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;
}凸包模板!!
最新推荐文章于 2025-07-01 21:13:28 发布
本文介绍了一个基于水平序的凸包算法实现,通过Graham扫描法找出二维平面上一系列点构成的凸包边界,并计算其周长。代码中定义了点结构体及用于比较和交叉乘计算的函数,实现了完整的Graham扫描过程。

3216

被折叠的 条评论
为什么被折叠?



