nyoj-253-LK的旅行(Graham算法和旋转卡壳)
1 /* 2 Name:nyoj-253-LK的旅行 3 Copyright: 4 Author: 5 Date: 2018/4/27 15:01:36 6 Description: 7 zyj的模板 8 */ 9 #include <iostream> 10 #include <cstdio> 11 #include <algorithm> 12 #include <cstring> 13 using namespace std; 14 const int MAXN = 100009; 15 struct Point 16 { 17 int x, y; 18 Point(int _x = 0, int _y = 0) 19 { 20 x = _x; 21 y = _y; 22 } 23 Point operator - (const Point &b)const 24 { 25 return Point(x - b.x, y - b.y); 26 } 27 int operator ^(const Point &b)const 28 { 29 return x * b.y - y * b.x; 30 } 31 int operator *(const Point &b)const 32 { 33 return x * b.x + y * b.y; 34 } 35 void input() 36 { 37 scanf("%d%d", &x, &y); 38 return ; 39 } 40 }; 41 // 距离的平方 42 int dist2(Point a, Point b) 43 { 44 return (a - b) * (a - b); 45 } 46 47 // 二维凸包 48 Point list[MAXN]; 49 int Stack[MAXN], top; 50 bool _cmp(Point p1, Point p2) 51 { 52 int tmp = (p1 - list[0]) ^ (p2 - list[0]); 53 if (tmp > 0) 54 { 55 return true; 56 } 57 else if (tmp == 0 && dist2(p1, list[0]) <= dist2(p2, list[0])) 58 { 59 return true; 60 } 61 else 62 { 63 return false; 64 } 65 } 66 void Graham(int n) 67 { 68 Point p0; 69 int k = 0; 70 p0 = list[0]; 71 for (int i = 1; i < n; i++) 72 { 73 if (p0.y > list[i].y || (p0.y == list[i].y && p0.x > list[i].x)) 74 { 75 p0 = list[i]; 76 k = i; 77 } 78 } 79 swap(list[k], list[0]); 80 sort(list + 1, list + n, _cmp); 81 if (n == 1) 82 { 83 top = 1; 84 Stack[0] = 0; 85 return ; 86 } 87 if (n == 2) 88 { 89 top = 2; 90 Stack[0] = 0; 91 Stack[1] = 1; 92 return ; 93 } 94 Stack[0] = 0; 95 Stack[1] = 1; 96 top = 2; 97 for (int i = 2; i < n; i++) 98 { 99 while (top > 1 && ((list[Stack[top - 1]] - list[Stack[top - 2]]) ^ (list[i] - list[Stack[top - 2]])) <= 0) 100 { 101 top--; 102 } 103 Stack[top++] = i; 104 } 105 return ; 106 } 107 // 旋转卡壳,求两点间距离平方的最大值 108 int rotating_calipers(Point p[],int n) 109 { 110 int ans = 0; 111 Point v; 112 int cur = 1; 113 for (int i = 0; i < n; i++) 114 { 115 v = p[i] - p[(i + 1) % n]; 116 while ((v ^ (p[(cur + 1) % n] - p[cur])) < 0) 117 { 118 cur = (cur + 1) % n; 119 } 120 ans = max(ans, max(dist2(p[i], p[cur]), dist2(p[(i + 1) % n], p[(cur + 1) % n]))); 121 } 122 return ans; 123 } 124 Point p[MAXN]; 125 int main() 126 { 127 int n; 128 cin>>n; 129 while (n--) 130 { 131 int m; 132 cin>>m; 133 for (int i = 0; i < m; i++) 134 { 135 list[i].input(); 136 } 137 Graham(m); 138 for (int i = 0; i < top; i++) 139 { 140 p[i] = list[Stack[i]]; 141 } 142 printf("%d\n", rotating_calipers(p, top)); 143 } 144 return 0; 145 }