RT,所有点都在x轴上,但是随机微小扰动也无法解决。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define db double
const db eps=1e-9;
inline int sgn(db a) {return a<-eps?-1:a>eps;}
inline int cmp(db a,db b){return sgn(a-b);}
//点或向量
struct P{
db x,y;
P operator +(P p){return {x+p.x,y+p.y};}
P operator -(P p){return {x-p.x,y-p.y};}
// P operator *(db d){return {x*d,y*d};}
db operator *(P p){return x*p.y-y*p.x;}
P operator /(db d){return {x/d,y/d};}
bool operator <(const P& p) const{
int c=cmp(x,p.x);
if(c) return c==-1;
return cmp(y,p.y)==-1;
}
bool operator ==(const P& o) const{
return cmp(x,o.x)==0 && cmp(y,o.y)==0;
}
db dot(P p){return x*p.x+y*p.y;}
// db det(P p){return x*p.y-y*p.x;}
//一些函数
db abs2(){return x*x+y*y;}
db abs() {return sqrt(abs2());}
db distTo(P p) {return (*this-p).abs();}
db alpha() {return atan2(y,x);}
void read() {cin>>x>>y;if(rand()%2) x+=eps;if(rand()%2) y+=eps;}
void write(){printf("(%lf,%lf)\n",x,y);}
P rot90() {return P{-y,x};}
P unit() {return *this/abs();}
int quad() const{
return sgn(y)==1 || (sgn(y)==0&&sgn(x)>=0);
}//判断象限
};
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define crossOp(p1,p2,p3) sgn(cross(p1,p2,p3))//折线方向
P tmp;
bool cmp1(P a,P b)
{
return (a-tmp).alpha()<(b-tmp).alpha();
}
vector<P> convexHull(int n,P *ps)
{
vector<P> qs(n*2);
if(n<=1)
{
qs.resize(1);
qs[0]=ps[0];
return qs;
}
sort(ps,ps+n);
tmp=ps[0];
// tmp.write();
sort(ps,ps+n,cmp1);
int k=0;
for(int i=0;i<n;qs[k++]=ps[i++])
while(k>1 && crossOp(qs[k-2],qs[k-1],ps[i])<=0) --k;
for(int i=n-2,t=k;i>=0;qs[k++]=ps[i--])
while(k>t && crossOp(qs[k-2],qs[k-1],ps[i])<=0) --k;
qs.resize(k-1);
return qs;
}
int n;
P a[100005];
int main()
{
// freopen("P2742_1.in","r",stdin);
srand(time(0));
scanf("%d",&n);
vector<P> out;
for(int i=0;i<n;i++)
a[i].read();
out=convexHull(n,a);
int k=out.size();
// for(int i=0;i<k;i++) out[i].write();
db ans=0;
for(int i=0;i<k-1;i++) ans+=(out[i+1]-out[i]).abs();
ans+=(out[0]-out[k-1]).abs();
printf("%.2lf",ans);
// for(int i=0;i<k;i++) out[i].write();
return 0;
}