求凸包加上一个圆周长。弧形部分加起来肯定等于圆周,直线部分等于凸包。
看了姿势,手敲一个凸包,终于调过了。。凸包求完的时候,自动是顺时针序。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <stdlib.h>
#include <math.h>
#include <stack>
using namespace std;
const int mod=1e9+7;
#define type int
#define Vector Point
const double PI = 3.14159265358979323;
struct Point{
type x,y;
Point(){
}
Point(int x,int y):x(x),y(y){
}
Point operator-(Point other){
return Point(x-other.x,y-other.y);
}
};
//向量点积
type Dot(Vector a,Vector b){
return a.x*b.x + a.y*b.y;
}
//向量叉积
type Cross(Vector a,Vector b){
return a.x*b.y - a.y*b.x;
}
//向量长度
double Length(Vector a){
return sqrt(a.x*a.x+a.y*a.y+0.0);
}
//两向量夹角
type Angle(Vector a,Vector b){
return acos(Dot(a,b) / (Length(a)*Length(b))+0.0);
}
Point pts[1010];
Point tubao[1010];
bool flag[1010];
bool cmp(const Point& a,const Point& b){
if(a.x==b.x)return a.y<b.y;
return a.x<b.x;
}
int main(){
int n,l;
cin>>n>>l;
for(int i=0;i<n;i++){
scanf("%d%d",&pts[i].x,&pts[i].y);
}
sort(pts,pts+n,cmp);
int cnt=0;
stack<Point> sta;
sta.push(pts[0]); sta.push(pts[1]);
for(int i=2;i<n;i++){
while(sta.size()>1){
Point top1=sta.top(); sta.pop();
Point top2=sta.top(); sta.push(top1);
Point ab=top1-top2;
Point bc=pts[i]-top1;
if(Cross(ab,bc)<=0){
sta.pop();
}else{
break;
}
}
sta.push(pts[i]);
}
while(sta.size()){
tubao[cnt++]=sta.top();
sta.pop();
}
reverse(pts,pts+n);
cnt--;
int part1=cnt;
sta.push(pts[0]); sta.push(pts[1]);
for(int i=2;i<n;i++){
while(sta.size()>1){
Point top1=sta.top(); sta.pop();
Point top2=sta.top(); sta.push(top1);
Point ab=top1-top2;
Point bc=pts[i]-top1;
if(Cross(ab,bc)<=0){
sta.pop();
}else{
break;
}
}
sta.push(pts[i]);
}
while(sta.size()){
tubao[cnt++]=sta.top();
sta.pop();
}
double ans=0;
for(int i=0;i<cnt-1;i++){
ans+=Length(tubao[i]-tubao[i+1]);
}
ans+=(PI*l*2);
printf("%.0f\n",ans);
return 0;
}