题解:
二维凸包裸题
按照x坐标为第一关键字,y坐标为第二关键字排序
然后相邻判断叉积用单调队列搞过去
正反都做一次就好了
代码:
#include <bits/stdc++.h> using namespace std; #define rint register int #define IL inline #define rep(i,h,t) for (int i=h;i<=t;++i) #define dep(i,t,h) for (int i=t;i>=h;--i) const int N=2e4; const double eps=1e-10; struct Point{ double x,y,r; Point(){}; Point(double x1,double y1) { x=x1; y=y1; } IL void jsr() { r=atan2(y,x); } Point operator -(const Point b) const { return Point(x-b.x,y-b.y); } double operator ^(const Point b) const { return x*b.y-y*b.x; } }p[N],q[N]; IL int dcmp(double x) { if (x<-eps) return(-1); else if (x>eps) return(1); else return(0); } bool cmp(Point x,Point y) { return dcmp(x.x-y.x)<0||(dcmp(x.x-y.x)==0&&dcmp(x.y-y.y)==-1); } int n,t; void push(Point now) { while (dcmp((now-q[t])^(q[t]-q[t-1]))>0) --t; q[++t]=now; } IL double dis(Point x,Point y) { return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y)); } int main() { ios::sync_with_stdio(false); cin>>n; rep(i,1,n) { double x,y; cin>>x>>y; p[i]=Point(x,y); p[i].jsr(); } sort(p+1,p+n+1,cmp); t=1; q[0]=q[t]=p[1]; rep(i,2,n) push(p[i]); dep(i,n-1,1) push(p[i]); double ans=0; rep(i,1,t-1) ans+=dis(q[i],q[i+1]); printf("%.2lf",ans); return 0; }