计算几何小家桶
只到旋转卡壳部分
参考://https://www.cnblogs.com/Xing-Ling/p/12102489.html
#include<bits/stdc++.h>
#define ldb long double
using namespace std;
const ldb PI = acos(-1.0);
const ldb INF = 1e100;
const ldb eps = 1e-10;
int read(){
int s=0,w=1; char ch=getchar();
while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
while(isdigit(ch))s=s*10+(ch^48),ch=getchar();
return s*w;
}
int sign(ldb a){return fabs(a)<eps?0:(a>0?1:-1);}
struct Vector{
ldb x,y;
Vector(ldb x=0,ldb y=0):x(x),y(y){}
void scan(){scanf("%Lf%Lf",&x,&y);}
void print(){printf("%.2Lf %.2Lf\n",x,y);}
ldb theta(){return atan2(y,x);}
};
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,ldb b){return Vector(a.x*b,a.y*b);}
bool operator==(Vector a,Vector b){return !sign(a.x-b.x)&&!sign(a.y-b.y);}
bool operator<(Vector a,Vector b){return sign(a.x-b.x)==0?sign(a.y-b.y)<0:sign(a.x-b.x)<0;}
ldb Dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
ldb Cro(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
ldb Dot(Vector o,Vector a,Vector b){return (a.x-o.x)*(b.x-o.x)+(a.y-o.y)*(b.y-o.y);}
ldb Cro(Vector o,Vector a,Vector b){return (a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x);}
ldb Dis(Vector a,Vector b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
ldb Dis2(Vector a,Vector b){return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}
ldb Len(Vector a){return sqrt(Dot(a,a));}
Vector Rotate(Vector a,ldb alpha){
ldb x=a.x*cos(alpha)+a.y*sin(alpha);
ldb y=-a.x*sin(alpha)+a.y*cos(alpha);
return Vector(x,y);
}
Vector Rotate(Vector a,Vector b,ldb alpha){
ldb x=(a.x-b.x)*cos(alpha)+(a.y-b.y)*sin(alpha);
ldb y=(b.x-a.x)*sin(alpha)+(a.y-b.y)*cos(alpha);
return Vector(x,y);
}
bool p_at_line(Vector p,Vector a,Vector b){
return !sign(Cro(p-a,b-a));
}
bool p_at_seg(Vector p,Vector a,Vector b){
return !sign(Cro(p-a,b-a))&&sign(Dot(p-a,p-b))<=0;
}
Vector p_to_line_foot(Vector p,Vector a,Vector b){
Vector x=p-a,y=p-b,z=b-a;
ldb len1=Dot(x,z)/Len(z),len2=-1.0*Dot(y,z)/Len(z);
return a+z*(len1/(len1+len2));
}
ldb p_to_line(Vector p,Vector a,Vector b){
if(a==b)return Dis(a,p);
Vector x=p-a,z=b-a;
return fabs(Cro(x,z)/Len(z));
}
ldb p_to_seg(Vector p,Vector a,Vector b){
if(a==b)return Dis(a,p);
Vector x=p-a,y=p-b,z=b-a;
if(sign(Dot(x,z))<0)return Len(x);
if(sign(Dot(y,z))>0)return Len(y);
return fabs(Cro(x,z)/Len(z));
}
Vector p_to_seg_foot(Vector p,Vector a,Vector b){
if(a==b)return a;
Vector x=p-a,y=p-b,z=b-a;
if(sign(Dot(x,z))<0)return a;
if(sign(Dot(y,z))>0)return b;
return p_to_line_foot(p,a,b);
}
Vector get_cross_ll(Vector a,Vector b,Vector c,Vector d){
Vector x=b-a,y=d-c,z=a-c;
return a+x*(Cro(y,z)/Cro(x,y));
}
bool cross_ls(Vector a,Vector b,Vector c,Vector d){
return p_at_seg(get_cross_ll(a,b,c,d),c,d);
}
int cross_ss(Vector a,Vector b,Vector c,Vector d){
if(!(sign(max(a.x,b.x)-min(c.x,d.x))!=-1&&sign(max(c.x,d.x)-min(a.x,b.x))!=-1
&&sign(max(a.y,b.y)-min(c.y,d.y))!=-1&&sign(max(c.y,d.y)-min(a.y,b.y))!=-1))return 0;//涓嶄氦
ldb x1=Cro(b-a,c-a),x2=Cro(b-a,d-a);
ldb y1=Cro(d-c,a-c),y2=Cro(d-c,b-c);
if(sign(x1)*sign(x2)==0&&sign(y1)*sign(y2)==0)return 2;//閲嶅悎
return sign(x1)*sign(x2)<=0&&sign(y1)*sign(y2)<=0;
}
Vector get_cross_ss(Vector a,Vector b,Vector c,Vector d){
int op=cross_ss(a,b,c,d);
if(op==0)return Vector(INF,op);
if(op==2){
if(a==c||a==d)return a;
if(b==c||b==d)return b;
return Vector(INF,op);
}
Vector x=b-a,y=d-c,z=a-c;
return a+x*(Cro(y,z)/Cro(x,y));
}
bool s_at_sleft(Vector o,Vector a,Vector b){//oa 鍦?ob 宸﹁竟锛堜笉鍚噸鍙狅級
return sign(Cro(a-o,b-o))<0;
}
bool s_at_sright(Vector o,Vector a,Vector b){
return sign(Cro(a-o,b-o))>0;
}
bool p_in_tri(Vector p,Vector a,Vector b,Vector c){
if(s_at_sleft(a,b,c))swap(b,c);
if(s_at_sleft(a,b,p))return false;
if(s_at_sleft(b,c,p))return false;
if(s_at_sleft(c,a,p))return false;
return true;
}
int p_in_poly(Vector *p,int n,Vector a){
int cnt=0; ldb tmp;
for(int i=1;i<=n;++i){
int j=i<n?i+1:1;
if(p_at_seg(a,p[i],p[j]))return 2;//杈逛笂
if(a.y>=min(p[i].y,p[j].y)&&a.y<max(p[i].y,p[j].y))
tmp=p[i].x+(a.y-p[i].y)/(p[j].y-p[i].y)*(p[j].x-p[i].x),cnt+=sign(tmp-a.x)>0;
}
return cnt&1;//1 鍐呴儴 0 澶栭儴
}
bool seg_in_poly(Vector *p,int n,Vector a,Vector b){
if(!p_in_poly(p,n,a)||!p_in_poly(p,n,b))return false;
p[0]=p[n],p[n+1]=p[1];
static Vector stk[100005]; int top=0;
stk[++top]=a,stk[++top]=b;
for(int i=1;i<=n;++i)if(cross_ss(a,b,p[i],p[i-1])){
if(p_at_seg(p[i],a,b)){stk[++top]=p[i];continue;}
if(p_at_seg(p[i-1],a,b)||p_at_seg(a,p[i-1],p[i])||p_at_seg(b,p[i-1],p[i]))continue;
return false;
}
sort(stk+1,stk+1+top);
for(int i=2;i<=top;++i)
if(!p_in_poly(p,n,Vector((stk[i-1].x+stk[i].x)/2,(stk[i-1].y+stk[i].y)/2)))return false;
return true;
}
bool poly_out_poly(Vector *a,int n,Vector *b,int m){
for(int i=1;i<=n;++i){
int j=i<n?i+1:1;
for(int i2=1;i2<=m;++i2){
int j2=i2<m?i2+1:1;
if(cross_ss(a[i],a[j],b[i2],b[j2]))return false;
if(p_in_poly(b,m,a[i])||p_in_poly(a,n,b[i2]))return false;
}
}
return true;
}
ldb polyarea(Vector *p,int n){
ldb s=0;
for(int i=1;i<=n;++i)
s+=Cro(p[i],p[i<n?i+1:1]);
return s/2.0;
}
// pair<int,int> Graham(Vector *p,int n,Vector *cv){
// sort(p+1,p+1+n);
// int top=0;
// for(int i=1;i<=n;++i){//涓嬪嚫澹?
// while(top>1&&sign(Cro(cv[top]-cv[top-1],p[i]-cv[top-1]))<=0)--top;
// cv[++top]=p[i];
// }
// int tmp=top;
// for(int i=n;i>=1;--i){//涓婂嚫澹?
// while(top>tmp&&sign(Cro(cv[top]-cv[top-1],p[i]-cv[top-1]))<=0)--top;
// cv[++top]=p[i];
// }
// return pair<int,int>(tmp,top-1);//1..tmp 涓嬪嚫,tmp+1..top-1 涓婂嚫
// }
Vector mn(INF,INF);
bool cmp(Vector a,Vector b){
ldb alpha=atan2(a.y-mn.y,a.x-mn.x),beta=atan2(b.y-mn.y,b.x-mn.x);
if(sign(alpha-beta)==0)return a.x<b.x;
else return alpha<beta;
}
int Graham(Vector *p,int n,Vector *cv){
int id,top=0;
for(int i=1;i<=n;++i)
if(mn.y>p[i].y||mn.y==p[i].y&&mn.x>p[i].x)mn=p[i],id=i;
swap(p[id],p[1]),sort(p+2,p+1+n,cmp);
cv[++top]=p[1];
for(int i=2;i<=n;++i){
while(top>1&&sign(Cro(cv[top]-cv[top-1],p[i]-cv[top-1]))<=0)--top;
cv[++top]=p[i];
}
return top;
}
int get_diameter_of_convex(Vector*p,int n){
int ans=0,j=3;
if(n==2)return Dis2(p[1],p[2]);
p[++n]=p[1];
for(int i=1;i<n;++i){
while(sign(Cro(p[j]-p[i],p[j]-p[i+1])-Cro(p[j+1]-p[i],p[j+1]-p[i+1]))<0)
j=(j+1)%n+1;
ans=max(ans,(int)max(Dis2(p[j],p[i]),Dis2(p[j],p[i+1])));
}
return ans;
}
Vector p[1000000],cv[1000000];
int n,l;
signed main(){
n=read(),l=read();
for(int i=1;i<=n;++i)p[i].scan();
int len=Graham(p,n,cv);
ldb ans=0;
for(int i=2;i<=len;++i)
ans+=Dis(cv[i],cv[i-1]);
ans+=Dis(cv[1],cv[len]);
printf("%d",(int)(ans+2*PI*l+0.5));
return 0;
}