/*
translation:
用一条线把若干个点包起来,并且线距离任何一个点的距离都不小于r。求这条线的最小距离是多少?
solution:
直接求凸包,然后凸包的周长加上一个圆的周长即可。
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 50000 + 5;
const double EPS = 1e-10;
const double pi = 3.14159265;
double add(double a, double b)
{
if(abs(a + b) < EPS * (abs(a) + abs(b))) return 0;
return a + b;
}
struct P
{
double x, y;
int id;
P(){}
P(double x_, double y_):x(x_),y(y_){}
bool operator < (const P& rhs) const {
return x < rhs.x || (x == rhs.x && y < rhs.y);
}
P operator + (P p) {
return P(add(x, p.x), add(y, p.y));
}
P operator - (P p) {
return P(add(x, -p.x), add(y, -p.y));
}
P operator * (double d) {
return P(x * d, y * d);
}
double dot(P p) { //内积
return add(x * p.x, y * p.y);
}
double det(P p) { //外积
return add(x * p.y, -y * p.x);
}
} ps[maxn];
int n, r;
double dist(P p, P q)
{
double ans = (p - q).dot(p - q);
return sqrt(ans);
}
bool cmp_id(const P& lhs, const P& rhs)
{
return lhs.id < rhs.id;
}
double graham()
{
sort(ps, ps + n);
int k = 0;
vector<P> res;
res.resize(n * 2);
for(int i = 0; i < n; i++) {
while(k > 1 && (res[k-1] - res[k-2]).det(ps[i] - res[k-1]) <= 0) k--;
res[k++] = ps[i];
}
for(int i = n - 2, t = k; i >= 0; i--) {
while(k > t && (res[k-1] - res[k-2]).det(ps[i] - res[k-1]) <= 0) k--;
res[k++] = ps[i];
}
res.resize(k - 1);
double len = 0;
sort(res.begin(), res.end(), cmp_id);
for(int i = 0; i < res.size()-1; i++)
len += dist(res[i], res[i+1]);
int s = res.size();
len += dist(res[0], res[s-1]);
return len;
}
int main()
{
//freopen("in.txt", "r", stdin);
while(~scanf("%d%d", &n, &r)) {
for(int i = 0; i < n; i++) {
cin >> ps[i].x >> ps[i].y;
ps[i].id = i;
}
double tmp = graham() + 2.0 * pi * r;
int ans = tmp + 0.5;
cout << ans << endl;
}
return 0;
}
poj1113(凸包)
最新推荐文章于 2020-05-03 23:27:33 发布