计算所有点的凸包,然后凸包的每条边向外平移 L,相邻边用弧填充,所有弧合起来恰好是一个圆。所以最终的长度为凸包所有边的长度加上圆的周长。
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 1005;
const double Pi = atan(1.0) * 4;
int cnt; //凸包中点的数量
struct point //点
{
int x;
int y;
}p[MAXN], ans[MAXN];
//排序方式
int cmp(point a, point b)
{
if (a.x != b.x)
return a.x < b.x;
else
return a.y < b.y;
}
//计算叉积
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);
}
//计算两点之间的距离
double length(point a, point b)
{
return sqrt(1.0 * (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
//计算凸包
void convex(int n)
{
sort(p, p + n, cmp);
cnt = 0;
for (int i = 0; i < n; i++) //凸包上部
{
while (cnt > 1 && cross(ans[cnt - 2], ans[cnt - 1], p[i]) >= 0)
--cnt;
ans[cnt++] = p[i];
}
int key = cnt;
for (int i = n - 2; i >= 0; i--) //凸包下部
{
while (cnt > key && cross(ans[cnt - 2], ans[cnt - 1], p[i]) >= 0)
--cnt;
ans[cnt++] = p[i];
}
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
int N, L;
scanf("%d%d", &N, &L);
for (int i = 0; i < N; i++) //输入点集
{
scanf("%d%d", &p[i].x, &p[i].y);
}
convex(N);
double sum = 2 * Pi * L; //圆弧的总长度
for (int i = 0; i < cnt - 1; i++) //凸包的总长度
sum += length(ans[i], ans[i + 1]);
printf("%.0lf\n", sum); //小数点后保留0位数字,四舍五入
if (T != 0)
printf("\n");
}
return 0;
}
继续加油。