# cogs 896 圈奶牛

PROGRAM NAME: fc

INPUT FORMAT(file fc.in)

OUTPUT FORMAT(file fc.out)

SAMPLE INPUT (file fc.in)

4
4 8
4 12
5 9.3
7 8

SAMPLE OUTPUT (file fc.out)

12.00

Graham扫描法

1. 将点按x坐标第一关键字，y坐标第二关键字排序
2. 首先将p1,p2压入栈中
3. 判断下一个点和栈中最后一个点组成的向量是否在当前前进方向的左边（求下凸壳），如果是的话就入栈，否则弹栈
4. 这样求出了下凸壳，再倒着做一遍就求出来了正凸壳，合起来就是完整的凸包

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#define N 50000
using namespace std;

const double eps=1e-7;
int dcmp(double x)
{
if (fabs(x)<eps) return 0;
else
if (x>0)
return 1;
else
return -1;
}

const double pi=acos(-1.0);

struct Vector
{
double x,y;
Vector (double a=0,double b=0)
{
x=a,y=b;
}
bool operator < (const Vector &a) const
{
return x<a.x||(x==a.x&&y<a.y);
}
};
typedef Vector Point;

struct Line
{
Point p;
Vector v;
Line(Point P=Point(0,0),Vector V=Vector(0,0))
{
p=P,v=V;
}
};

Vector operator + (Vector a,Vector b) {return Vector(a.x+b.x,a.y+b.y);}
Vector operator - (Vector a,Vector b) {return Vector(a.x-b.x,a.y-b.y);}
Vector operator * (Vector a,double b) {return Vector(a.x*b  ,a.y*b  );}
Vector operator / (Vector a,double b) {return Vector(a.x/b  ,a.y/b  );}
bool   operator ==(Vector a,Vector b) {return !dcmp(a.x-b.x)&&!dcmp(a.y-b.y);}

Vector Rotate(Vector a,double rad)
{
}

double Dot(Vector a,Vector b)
{
return a.x*b.x+a.y*b.y;
}

double Len(Vector a){return sqrt(Dot(a,a));}

double Angle(Vector a,Vector b){return acos(Dot(a,b)/Len(a)/Len(b));}

double Cross(Vector a,Vector b)
{
return a.x*b.y-a.y*b.x;
}

Vector Normal(Vector a)
{
return Vector(-a.y/Len(a),a.x/Len(a));
}

Point Line_cross(Line a,Line b)
{
Vector u=a.p-b.p;
double t=Cross(b.v,u)/Cross(a.v,b.v);
return a.p+a.v*t;
}

double Dis_To_Line(Point p,Point a,Point b)
{
return fabs(Cross(a-b,p-b)/Len(a-b));
}

double Dis_To_Seg(Point p,Point a,Point b)
{
if (a==b) return Len(p-a);
Vector v=b-a,w=p-a,u=p-b;
if (dcmp(Dot(v,w)<0))	return Len(w);
else if (dcmp(Dot(v,u))>0)	return Len(v);
else return fabs(Cross(v,w)/Len(v));
}

bool Line_Seg_Cross(Point l1,Point l2,Point a,Point b)
{
Vector v=l1-l2,w=a-l1,u=b-l2;
return dcmp(Cross(v,w))!=dcmp(Cross(v,u));
}

bool Seg_Cross(Point a1,Point a2,Point b1,Point b2)
{
double c1=Cross(a2-a1,b1-b1),c2=Cross(a2-a1,b2-a1),
c3=Cross(b2-b1,a1-b1),c4=Cross(b2-b1,a2-b1);
return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
}

Point Line_Pro(Point p,Point a,Point b)
{
Vector v=b-a;
return a+v*(Dot(v,p-a)/Dot(v,v));
}

double Area_T(Point a, Point b,Point c)
{
return Cross(b-a,c-a)*0.5;
}

Point TC(Point a,Point b,Point c)
{
Point p=(a+b)/2,q=(a+c)/2;
Vector v=Rotate(b-a,pi/2),w=Rotate(c-a,pi/2);
if (!dcmp(Cross(v,w)))
{
if (dcmp(Len(a-b)+Len(b-c)-Len(a-c))==0)
return (a+c)/2;
if (dcmp(Len(a-c)+Len(b-c)-Len(a-b))==0)
return (a+b)/2;
if (dcmp(Len(a-b)+Len(a-c)-Len(b-c))==0)
return (b+c)/2;
}
return Line_cross(Line(p,v),Line(q,w));
}

Point TG(Point a,Point b,Point c)
{
return (a+b+c)/3;
}

double Area_P(Point ploy[],int num)
{
double area=0;
for (int i=2;i<num;i++)
area+=Cross(ploy[i]-ploy[1],ploy[i+1]-ploy[1]);
return area/2;
}

bool Point_In_Ploy(Point p,Point poly[],int num)
{
int ans=0,k,d1,d2;
for (int i=1;i<=num;i++)
{
if (!dcmp(Dis_To_Seg(p,poly[i],poly[i%num+1]))) return 0;
k=dcmp(Cross(poly[i%num+1]-poly[i],p-poly[i]));
d1=dcmp(poly[i].y-p.y);
d2=dcmp(poly[i%num+1].y-p.y);
if (k>0&&d1<=0&&d2>0) ++ans;
if (k<0&&d1>=0&&d2<0) --ans;
}
if (ans) return 1;
return 0;
}

Point stack[N];int top;
void Graham(Point p[],int num)
{
memset(stack,0,sizeof stack);top=0;
sort(p+1,p+num+1);
for (int i=1;i<=num;i++)
{
while (top>1 && dcmp(Cross(stack[top]-stack[top-1],p[i]-stack[top-1]))<=0)
top--;
stack[++top]=p[i];
}
int k=top;
for (int i=num-1;i>=1;i--)
{
while (top>k && dcmp(Cross(stack[top]-stack[top-1],p[i]-stack[top-1]))<=0)
top--;
stack[++top]=p[i];
}
if (num>1) top--;
}

main()
{
freopen("fc.in","r",stdin);
freopen("fc.out","w",stdout);
int n;
scanf("%d",&n);
double x1,x2,x3,x4,y1,y2,y3,y4;
Point p[N];
for (int i=1;i<=n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
Graham(p,n);
double ans=0;
for (int i=2;i<=top;i++)
ans+=Len(stack[i]-stack[i-1]);
ans+=Len(stack[top]-stack[1]);
printf("%.2lf",ans);
}