解题思路:先用Graham找出凸包,并算出凸包的周长再加上一个以L为半径的圆的周长就是所求的答案,因为凸多边形的内角和为(n-2)*180,n*360-(2*90)*n-(n-2)*180=360,刚好是一个完整的圆。
代码
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define PI 3.14159265358979
#define exchange(a, b) {point t;t=a; a=b; b=t;}
const int maxN = 1000;
typedef struct {
long x;
long y;
}point;
int N, L, top=0;
point pl[maxN+1];
double direction(point p1, point p2, point p3, point p4) {
return (p2.x-p1.x)*(p4.y-p3.y)-(p4.x-p3.x)*(p2.y-p1.y);
}
double dis(point p1, point p2) {
return sqrt(1.0*(p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
}
int cmp(const void * arg1, const void * arg2) {
point *a, *b;
double d, dis1, dis2;
a = (point *)arg1;
b = (point *)arg2;
d = direction(pl[1], *b, pl[1], *a);
dis1 = dis(pl[1], *a);
dis2 = dis(pl[1], *b);
if( d!=0 ) {
return (int)d;
}
else if(dis1 > dis2){
return 1;
}
else if(dis1 <dis2 ) {
return -1;
}
else {
return 0;
}
}
void push(point stack[], point p) {
top++;
stack[top] = p;
}
point pop(point stack[]) {
top--;
return stack[top+1];
}
int Graham_scan(point stack[]) {
int i;
push(stack, pl[1]);
push(stack, pl[2]);
for ( i=3; i<=N; i++ ) {
while(top>=2 && direction(stack[top-1], stack[top], stack[top], pl[i])<=0 ) {
pop(stack);
}
push(stack, pl[i]);
}
return top;
}
int main() {
int i, num;
point stack[maxN+1];
double d=0;
freopen("input.in", "r", stdin);
scanf("%d%d",&N, &L);
for ( i=1; i<=N; i++ ) {
scanf("%d%d", &pl[i].x, &pl[i].y);
if(i>1 && (pl[i].y<pl[1].y || (pl[i].y==pl[1].y && pl[i].x<pl[1].x))) {
exchange(pl[i], pl[1]);
}
}
qsort((void *)(pl+2), N-1, sizeof(point), cmp);
num = Graham_scan(stack);
for ( i=1; i<num; i++ ) { //计算凸多边形的边长
d += dis(stack[i], stack[i+1]);
}
d += dis(stack[1], stack[num]);
d += (2*PI*L); //加上圆的周长
printf("%.f\n", d);
return 0;
}