旋转卡壳 凸包周长

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include<bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
int sign(double x) { // 符号函数
if (fabs(x) < eps) return 0;//x是0
if (x < 0) return -1;//x是负数
return 1;//x是正数
}
struct Point{
double x, y;
Point(double x = 0, double y = 0) : x(x), y(y) { }
Point operator +(Point B){return Point(x+B.x,y+B.y);}
Point operator -(Point B){return Point(x-B.x,y-B.y);}
Point operator *(double k){return Point(x*k,y*k);}
Point operator /(double k){return Point(x/k,y/k);}
bool operator == (Point B){return sign(x-B.x)==0&&sign(y-B.x)==0;}
bool operator <(Point B)//排序
{return sign(x-B.x)<0||sign(x-B.x)==0&&sign(y-B.y)<0;}

};
double cross(Point a, Point b){//外积(叉积)
//向量A与B张成的平行四边形的有向面积。B在A的逆时针方向为正。
//如果等0则,两个向量平行
return a.x * b.y - b.x * a.y;
}
double area(Point a, Point b, Point c){
//计算向量AB与AC构成的平行四边形有向面积
return cross(b-a, c-a);
}
double get_len(Point a,Point b){
Point A=a-b;//两点所成线段距离
double W=A.x*A.x+A.y*A.y;
W=sqrt(W);
return W;
}
const int N=1e5+10;
Point a[N];
int n,stk[N];
bool used[N];
vector<int>convex;
double andrew(){
sort(a+1,a+1+n);//最左右两点属于凸包上点
int top=0;
for(int i=1;i<=n;i++){//凸包上链边
while(top>=2){
double B=area(a[stk[top-1]],a[i],a[stk[top]]);
int A=sign(B);
if(A>=0)
used[stk[top--]]=false;
else break;
}
stk[++top]=i;
used[i]=true;
}
for(int i=1;i<top;i++)//不加最右点
convex.push_back(stk[i]);
used[1]=false;used[n]=false;
top=0;
for(int i=n;i>=1;i--){//上链边
if(used[i]) continue;
while(top>=2){
double B=area(a[stk[top-1]],a[i],a[stk[top]]);
int A=sign(B);
if(A>=0)
used[stk[top--]]=false;
else break;
}
stk[++top]=i;
used[i]=true;
}
for(int i=1;i<top;i++)//不加最左点
convex.push_back(stk[i]);
double res=0;
for(int i=0;i<convex.size();i++){//围成圈的各个点
res+=get_len(a[convex[(i + 1) % convex.size()]] , a[convex[i]]);
}
return res;
}
void solve(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].x>>a[i].y;
}
double res=andrew();
cout<<fixed<<setprecision(2)<<res;
}
signed main(){
solve();
return 0;
}