博客原文地址:http://blog.csdn.net/xuechelingxiao/article/details/39023795
题目大意:给出多边形城堡的所有顶点,在外围建一圈城墙,城墙距离城堡的距离至少为L,求城墙的最小长度。
解题思路:其实所求问题可以转换成两部分,一部分是以多边形围城的凸包的长度,另一部分则是凸包向外扩L之后,剩下的部分会填补成一个整圆。
如图:
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std;
const double eps = 1e-8;
const double Pi = acos(-1.0);
struct Point {
double x, y;
} P[1005], p[1005], convex[1005];
int dcmp(double x) {
return x < -eps ? -1 : x > eps;
}
double xmult(Point a, Point b, Point c){
return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x);
}
double Distance(Point a, Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(Point a, Point b){
if(dcmp(xmult(a, b, P[0])) == 0){
return Distance(a, P[0]) < Distance(b, P[0]);
}
else {
return dcmp(xmult(a, b, P[0])) > 0;
}
}
int cmpp(Point a, Point b){
if(a.x-b.x < eps) return a.y-b.y < eps;
else return a.x-b.x < eps;
}
int Remove(int n){ //remove repeat points
int m = 1;
sort(p, p+n, cmpp);
P[0] = p[0];
for(int i = 1; i < n; ++i){
if(!dcmp(p[i].x-p[i-1].x) == 0 ||
!dcmp(p[i].y-p[i-1].y) == 0){
P[m++] = p[i];
}
}
return m;
}
int Graham(int n){
int m = n;//Remove(n);
int s = 0, top = 1;
for(int i = 0; i < m; ++i){
if(P[i].y < P[s].y ||
(P[i].y == P[s].y && P[i].x < P[s].x)){
s = i;
}
}
if(s != 0){
Point tmp = P[0]; P[0] = P[s]; P[s] = tmp;
}
sort(P+1, P+m, cmp);
convex[0] = P[0], convex[1] = P[1];
for(int i = 2; i < m; ++i){
while(top > 0 &&
dcmp(xmult(convex[top], P[i], convex[top-1])) <= 0){
//if need point on the convex hull,use <
top--;
}
convex[++top] = P[i];
}
return top+1;
}
int main()
{
double r;
int n;
scanf("%d%lf", &n, &r);
for(int i = 0; i < n; ++i) {
scanf("%lf%lf", &P[i].x, &P[i].y);
}
int m = Graham(n);
double ans = 0;
for(int i = 0; i < m; ++i) {
ans += Distance(convex[i], convex[(i+1)%m]);
}
ans += 2*Pi*r;
printf("%.0f\n", ans);
return 0;
}