题目简介
给定平面上的n个点及半径r,求圆的周长与凸包周长之和。
说明
记录一下Graham求凸包的模板。
#include <bits/stdc++.h>
using namespace std;
const double PI = acos(-1.0);
const int maxn = 1005;
struct point {int x, y;}p[maxn];
int s[maxn], top;
inline int cross(point p0, point p1, point p2)
{
return (p1.x-p0.x) * (p2.y-p0.y) - (p1.y-p0.y) * (p2.x-p0.x);
}
inline double dis(point p1, point p2)
{
return sqrt((p2.x-p1.x)*(p2.x-p1.x) + (p2.y-p1.y)*(p2.y-p1.y));
}
inline bool cmp(point p1, point p2)
{
int c = cross(p[0], p1, p2);
if (c > 0) return 1;
else if (!c && dis(p[0], p1) < dis(p[0], p2)) return 1;
return 0;
}
inline void graham(int n)
{
s[0] = 0;
if (n == 1) top = 0;
else
{
s[1] = top = 1;
if (n == 2) return;
for (int i = 2; i < n; ++i)
{
while (top && cross(p[s[top-1]], p[s[top]], p[i]) <= 0)
--top;
s[++top] = i;
}
}
}
int main()
{
int n, r;
double ans;
while (cin >> n >> r)
{
scanf("%d%d", &p[0].x, &p[0].y);
point p0;
p0.x = p[0].x; p0.y = p[0].y;
int k = 0;
for (int i = 1; i < n; ++i)
{
scanf("%d%d", &p[i].x, &p[i].y);
if ((p0.y>p[i].y) || ((p0.y==p[i].y)&&(p0.x>p[i].x)))
{
p0.x = p[i].x;
p0.y = p[i].y;
k = i;
}
}
p[k] = p[0];
p[0] = p0;
sort(p+1, p+n, cmp);
graham(n);
ans = 2 * PI * r;
for (int i = 0; i <= top; ++i)
ans += dis(p[s[i]], p[s[(i+1) % (top+1)]]);
printf("%d\n", (int)(ans+0.5));
}
return 0;
}