DESCRIPTION
农夫约翰想要建造一个围栏用来围住他的奶牛,可是他资金匮乏。他建造的围栏必须包括他的奶牛喜欢吃草的所有地点。对于给出的这些地点的坐标,计算最短的能够围住这些点的围栏的长度。
INPUT FORMAT
输入数据的第一行包括一个整数 N。N(0 <= N <= 10,000)表示农夫约翰想要围住的放牧点的数目。接下来 N 行,每行由两个实数组成,Xi 和 Yi,对应平面上的放牧点坐标(-1,000,000 <= Xi,Yi <= 1,000,000)。数字用小数表示。
OUTPUT FORMAT
输出必须包括一个实数,表示必须的围栏的长度。答案保留两位小数。
SAMPLE INPUT
4
4 8
4 12
5 9.3
7 8
SAMPLE OUTPUT
12.00
SOLUTION
一道模板题
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#define eps 10e-6
using namespace std;
struct Point{
double x,y;
Point(double x=0,double y=0):x(x),y(y){}
Point operator + (const Point p)
{
return Point(x+p.x,y+p.y);
}
Point operator - (const Point p)
{
return Point(x-p.x,y-p.y);
}
}p[10005],ch[10005];
typedef Point Vector;
int n;
int dcmp(double x)
{
if(fabs(x)<eps)return 0;
return x>0?1:-1;
}
double Cross(Vector A,Vector B)
{
return A.x*B.y-A.y*B.x;
}
double Dis(Point A,Point B)
{
return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}
bool operator < (const Point& A,const Point& B)
{
if(A.x!=B.x)return A.x<B.x;
return A.y<B.y;
}
int ConvexHull()
{
sort(p+1,p+1+n);
int top=0;
for(int i=1;i<=n;i++)
{
while(top>1&&dcmp(Cross(p[i]-ch[top],ch[top]-ch[top-1]))<=0)top--;
ch[++top]=p[i];
}
int k=top;
for(int i=n-1;i>=1;i--)
{
while(top>k&&dcmp(Cross(p[i]-ch[top],ch[top]-ch[top-1]))<=0)top--;
ch[++top]=p[i];
}
return top;
}
double PolyCirc(int m)
{
double c=0;
for(int i=1;i<m;i++)
{
c+=Dis(ch[i+1],ch[i]);
}
return c;
}
int main()
{
//freopen("fc.in","rb",stdin);
//freopen("fc.out","wb",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
}
printf("%.2lf",PolyCirc(ConvexHull()));
return 0;
}