这是一道凸包的模板题
相对于Graham的$O(nlogn)$和Jarvis步进法$O(n*h)$,h是凸包顶点数
我更偏向于使用Graham扫描法的变种Andrew算法
原因在于,扫描法会产生回退,糟糕的情况下,时间复杂度会升高
但Anrew的思路是分治,构建凸包的上链和下链,这样会更加稳定
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
typedef long long ll;
const double eps=1e-8;
int sgn(double x)
{
if (fabs(x)<eps) return 0;
return x<0?-1:1;
}
struct Point
{
double x,y;
Point (){}
Point (double x,double y):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 sgn(x-B.x)==0&&sgn(y-B.x)==0;}
bool operator <(Point B){return sgn(x-B.x)<0||sgn(x-B.x)==0&&sgn(y-B.y)<0;}
};
double Distance(Point A, Point B){return hypot(A.x-B.x,A.y-B.y);}
double Cross(Point A,Point B){return A.x*B.y-A.y*B.x;}
const int N=1e4+100;
Point p[N],res[N];
int Convex_hull(Point *p,int n,Point *ch)
{
sort(p,p+n);
n=unique(p,p+n)-p;
int v=0;
for(int i=0;i<n;i++)
{
while(v>1&&sgn(Cross(ch[v-1]-ch[v-2],p[i]-ch[v-2]))<=0)
v--;
ch[v++]=p[i];
}
int j=v;
for(int i=n-2;i>=0;i--)
{
while(v>j&&sgn(Cross(ch[v-1]-ch[v-2],p[i]-ch[v-2]))<=0)
v--;
ch[v++]=p[i];
}
if (n>1) v--;
return v;
}
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
int num=Convex_hull(p,n,res);
double minn=0;
for(int i=0;i<num;i++)
minn+=Distance(res[i],res[(i+1)%num]);
printf("%.2f",minn);
return 0;
}