自己的第一法凸包
思路就是,建立凸包,求凸包周长加上圆的周长,主要练模版
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
const double eps=1e-8;
const double PI=acos(-1);
const int maxn=1000+10;
int N,L;
int top;
using namespace std;
int sgn(double x){
if(fabs(x)<eps)
return 0;
if(x>0)
return 1;
if(x<0)
return -1;
}
struct point{
int x,y;
point() {}
point(int _x,int _y){
x=_x;
y=_y;
}
};
typedef point vector;
vector operator + (vector A,vector B){
return point(A.x+B.x,A.y+B.y);
}
vector operator - (point A,point B){
return point(A.x-B.x,A.y-B.y);
}
int operator ^ (vector A,vector B){
return A.x*B.y-A.y*B.x;
}
int operator * (vector A,vector B){
return A.x*B.x+A.y*B.y;
}
bool operator < (vector A,vector B){
return A.x<B.x || A.x==B.x && A.y<B.y;
}
bool operator == (point a,point b){
return sgn(a.x-b.x)==0 && sgn(a.y-b.y)==0;
}
double dis(point a,point b){
return hypot(a.x-b.x,a.y-b.y);
}
struct convex{
int n;
point p[maxn];
};
convex t;
point p[maxn];
bool cmp(point a,point b){ //极角排序函数
int d=(a-p[0])^(b-p[0]);
if(d==0&&sgn(dis(a,p[0])-dis(b,p[0])) < 0 || d>0)//共线时取较近的点
return true;
return false;
}
void init(){ //找到初始点
for(int i=0;i<N;i++)
if(p[i]<p[0])
swap(p[i],p[0]);
}
void graham(int n) //graham-scan
{
n=N;
if(n==1){
top=1;
t.p[0]=p[0];
}
else if(n==2){
top=2;
t.p[0]=p[0];t.p[1]=p[1];
if(t.p[0]==t.p[1])
top--;
}
else{
t.p[0]=p[0];t.p[1]=p[1];
top=2;
for(int i=2;i<n;i++){
while(top>1 && sgn((t.p[top-1]-t.p[top-2])^(p[i]-t.p[top-2])) <= 0)
top--;
t.p[top]=p[i];
top++;
}
}
}
double solve(){
double res=2*PI*L;
init();
sort(p+1,p+N,cmp);
graham(N);
/*for(int i=0;i<top;i++)
printf("(%d,%d)\n",t.p[i].x,t.p[i].y);*/
for(int i=0;i<top;i++)
res+=dis(t.p[i],t.p[(i+1)%top]);
return res;
}
int main(){
//freopen("input.txt","r",stdin);
while(~scanf("%d%d",&N,&L)){
double res;
for(int i=0;i<N;i++){
int x,y;
scanf("%d%d",&x,&y);
p[i]=point(x,y);
}
res=solve();
printf("%d\n",int(res+0.5));
}
return 0;
}