1 /* 2 * 凸包 3 * 注意:给出的点为整点数,不要设某一精度值! 4 */ 5 6 #include <cmath> 7 #include <cstdio> 8 #include <cstdlib> 9 #include <iostream> 10 11 using namespace std; 12 13 const int N = 1005; 14 const double PI = 3.1415927; 15 16 struct point { 17 double x; 18 double y; 19 }p[N], stack[N]; 20 21 double dis(point A, point B) { 22 return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)); 23 } 24 25 double crossProd(point A, point B, point C) { 26 return (B.x-A.x)*(C.y-A.y) - (B.y-A.y)*(C.x-A.x); 27 } 28 29 //以最左下的点为基准点,其他各点(逆时针方向)以极角从小到大的排序规则 30 int cmp(const void *a, const void *b) { 31 point *c = (point *)a; 32 point *d = (point *)b; 33 double k = crossProd(p[0], *c, *d);//极角大小转化为求叉乘 34 if (k<0 || !k && dis(p[0], *c)>dis(p[0], *d)) return 1; 35 return -1; 36 } 37 38 double Graham(int n) { 39 double x = p[0].x; 40 double y = p[0].y; 41 int mi = 0; 42 for (int i=1; i<n; ++i) {//找到最左下的一个点 43 if (p[i].x<x || (p[i].x==x && p[i].y<y)) { 44 x = p[i].x; 45 y = p[i].y; 46 mi = i; 47 } 48 } 49 point tmp = p[mi]; 50 p[mi] = p[0]; 51 p[0] = tmp; 52 qsort(p+1, n-1, sizeof(point), cmp); 53 p[n] = p[0]; 54 stack[0] = p[0]; 55 stack[1] = p[1]; 56 stack[2] = p[2]; 57 int top = 2; 58 for (int i=3; i<=n; ++i) {//加入一个点后,向右偏拐或共线,则上一个点不在凸包内,则--top,该过程直到不向右偏拐或没有三点共线的点 59 while (crossProd(stack[top-1], stack[top], p[i])<=0 && top>=2) --top; 60 stack[++top] = p[i];//在当前情况下符合凸包的点,入栈 61 } 62 double len = 0; 63 for (int i=0; i<top; ++i) len += dis(stack[i], stack[i+1]); 64 return len; 65 } 66 67 int main() { 68 int t; 69 while (scanf("%d", &t) != EOF) { 70 while (t--) { 71 int n, l; 72 scanf ("%d%d", &n, &l); 73 for (int i=0; i<n; ++i) scanf ("%lf%lf", &p[i].x, &p[i].y); 74 double ans = Graham(n); 75 ans += PI * (l + l); 76 printf ("%.0lf\n", ans); 77 if (t) printf ("\n"); 78 } 79 } 80 return 0; 81 }