题意:
给定多边形城堡的n个顶点,绕城堡外面建一个围墙,围住所有点,并且墙与所有点的距离至少为L,求这个墙最小的长度。
思路:
城堡围墙长度最小值 = 凸包总边长 + 半径为L的圆周长
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <cctype>
#define mst(a,b) memset(a,b,sizeof(a))
typedef long long LL;
using namespace std;
const int N = 1001;
const double PI = 3.14159265358979323846;
int top=-1,n;
struct Point{
int x,y;
}p[N],stack[N];
int multi(Point p1,Point p2,Point p3){//p1p2 × p1p3
return (p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y);
}
int dis(Point p1,Point p2)//距离的平方
{
return (p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y) ;
}
bool cmp(Point a, Point b){//极角排序
int t=multi(p[0],a,b);
if(t>0) return true;
if(t==0&&(dis(p[0],a)<dis(p[0],b))) return 1;
return 0;
}
void graham(){
//找到最左下的点放在数组最前面
for(int i=1;i<n;i++){
if(p[i].y<p[0].y) swap(p[i],p[0]);
else if(p[i].y==p[0].y&&p[i].x<p[0].x) swap(p[i],p[0]);
}
sort(p+1,p+n,cmp);
for(int i=0;i<3;i++)
stack[i]=p[i];
top=2;
for(int i=3;i<n;i++){
while(top&&multi(stack[top-1],stack[top],p[i])<=0) top--;
stack[++top]=p[i];
}
}
int main(){
int T;
cin>>T;
while(T--){
int l;
cin>>n>>l;
for(int i=0;i<n;i++){
cin>>p[i].x>>p[i].y;
}
graham();
double ans=0;
for(int i=0;i<=top;i++){
double len=(double)sqrt((double)dis(stack[i],stack[(i+1)%(top+1)]));
ans+=len;
}
ans+=(double)2*PI*l;
printf("%.0lf\n",ans);
if(T) putchar(10);
}
return 0;
}