有个由N个点组成的多边形,现在要在这个多边形外至少L的距离修围墙,求围墙长度最短多少。
感受一下,就是凸包周长加上一个圆周长。
问:凹下去的怎么办?
答:凹下去就长了。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<cmath>
using namespace std;
const int maxn = 1005;
#define INF 1e9
#define EPS 1e-6
struct point {
int x,y;
point(){}
point(int _x,int _y) :x(_x),y(_y){}
point operator - (const point &a) {return point(x-a.x,y-a.y);}
};
int cross(point a,point b) {return a.x*b.y-a.y*b.x;}
double dis(point a,point b) {point c=a-b;return sqrt(1.0*c.x*c.x+1.0*c.y*c.y);}
bool cmp(point a,point b) {return a.x<b.x || (a.x==b.x && a.y<b.y);}
point P[maxn],hull[maxn];
int cnt=0;
int s[maxn];
int N,L;
void quickhull(int L,int R,point a,point b) {
int x=L,i=L-1,j=R+1;
for(int k = L; k <= R; k++ ) if( s[k] > s[x] || (s[x]==s[k] && cmp(P[x],P[k])))x=k;
point y = P[x];
for(int k = L; k <= R; k++ ) {
s[++i] = cross(a-P[k],y-P[k]);
if( s[i] > 0 ) swap(P[i],P[k]); else i--;
}
for(int k = R; k >= L; k-- ) {
s[--j] = cross(y-P[k],b-P[k]);
if( s[j] > 0 ) swap(P[j],P[k]); else j++;
}
if( L <= i ) quickhull(L,i,a,y);
hull[++cnt] = y;
if( j <= R ) quickhull(j,R,y,b);
}
int main() {
scanf("%d%d",&N,&L);
int x = 0;
P[0] = point(INF,INF);
for(int i = 1; i <= N; i++) {
scanf("%d%d",&P[i].x,&P[i].y);
if( cmp(P[i],P[x])) x=i;
}
swap(P[1],P[x]);
hull[++cnt] = P[1];
quickhull(2,N,P[1],P[1]);
double ans = 3.1415926*2.0*L;
hull[++cnt] = P[1];
for(int i = 2; i <= cnt; i++) ans += dis(hull[i],hull[i-1]);
printf("%.0lf\n",ans);
}