題意
給出平面上n個點的座標。你需要建一個圍牆,把所有的點圍在裡面,且圍牆距所有點的距離不小於l。求圍牆的最小長度。
(n leqslant 10^5)
Sol
首先考慮如果沒有l的限制,那麼顯然就是凸包的長度。
現在了距離的限制,那麼顯然原來建在凸包上的圍牆要向外移動(l)的距離,同時會增加一些沒有圍住的位置
因為多邊形的外交和為360,再根據補角的性質,畫一畫圖就知道這一塊是一個半徑為(l)的圓。
因為總答案為凸包周長 + (2 pi l)
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN = 1e5 + 10;
inline int read() {
char c = getchar(); int x = 0, f = 1;
while(c < `0` || c > `9`) {if(c == `-`) f = -1; c = getchar();}
while(c >= `0` && c <= `9`) x = x * 10 + c - `0`, c = getchar();
return x * f;
}
int N, top;
struct Point {
double x, y;
Point operator - (const Point &rhs) const {
return {x - rhs.x, y - rhs.y};
}
Point operator + (const Point &rhs) const {
return {x + rhs.x, y + rhs.y};
}
double operator ^ (const Point &rhs) const {
return x * rhs.y - y * rhs.x;
}
bool operator < (const Point &rhs) const {
return x == rhs.x ? y < rhs.y : x < rhs.x;
}
}p[MAXN], q[MAXN];
template<typename A> A sqr(A x) {
return x * x;
}
double dis(Point a, Point b) {
return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));
}
void insert(Point now) {
while(top > 1 && ((q[top] - q[top - 1]) ^ (now - q[top - 1])) < 0) top--;
q[++top] = now;
}
int main() {
N = read(); double L = read();
for(int i = 1; i <= N; i++) p[i].x = read(), p[i].y = read();
sort(p + 1, p + N + 1);
q[top = 1] = p[1];
for(int i = 2; i <= N; i++) insert(p[i]);
for(int i = N - 1; i >= 1; i--) insert(p[i]);
double ans = 0;
for(int i = 1; i < top; i++) ans += dis(q[i], q[i + 1]);
ans += 2 * acos(-1) * L + 0.5;
printf("%d
", (int) ans);
}