题意:求所有正方形中两点距离最大值的平方值。
思路:旋转卡壳法。
分别用数组和vector存凸包时,旋转卡壳代码有所不同。
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 #include<iostream> 6 #include<memory.h> 7 #include<cstdlib> 8 #include<vector> 9 #define clc(a,b) memset(a,b,sizeof(a)) 10 #define LL long long int 11 #define up(i,x,y) for(i=x;i<=y;i++) 12 #define w(a) while(a) 13 using namespace std; 14 const double inf=0x3f3f3f3f; 15 const int N = 4010; 16 const double eps = 5*1e-13; 17 const double PI = acos(-1.0); 18 using namespace std; 19 20 struct Point 21 { 22 int x, y; 23 Point(int x=0, int y=0):x(x),y(y) { } 24 }; 25 26 typedef Point Vector; 27 28 Vector operator - (const Point& A, const Point& B) 29 { 30 return Vector(A.x-B.x, A.y-B.y); 31 } 32 33 int Cross(const Vector& A, const Vector& B) 34 { 35 return A.x*B.y - A.y*B.x; 36 } 37 38 int Dot(const Vector& A, const Vector& B) 39 { 40 return A.x*B.x + A.y*B.y; 41 } 42 43 int Dist2(const Point& A, const Point& B) 44 { 45 return (A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y); 46 } 47 48 bool operator < (const Point& p1, const Point& p2) 49 { 50 return p1.x < p2.x || (p1.x == p2.x && p1.y < p2.y); 51 } 52 53 bool operator == (const Point& p1, const Point& p2) 54 { 55 return p1.x == p2.x && p1.y == p2.y; 56 } 57 58 // 点集凸包 59 // 如果不希望在凸包的边上有输入点,把两个 <= 改成 < 60 // 注意:输入点集会被修改 61 vector<Point> ConvexHull(vector<Point>& p) 62 { 63 // 预处理,删除重复点 64 sort(p.begin(), p.end()); 65 p.erase(unique(p.begin(), p.end()), p.end()); 66 67 int n = p.size(); 68 int m = 0; 69 vector<Point> ch(n+1); 70 for(int i = 0; i < n; i++) 71 { 72 while(m > 1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--; 73 ch[m++] = p[i]; 74 } 75 int k = m; 76 for(int i = n-2; i >= 0; i--) 77 { 78 while(m > k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--; 79 ch[m++] = p[i]; 80 } 81 if(n > 1) m--; 82 ch.resize(m); 83 return ch; 84 } 85 86 // 返回点集直径的平方 87 int diameter2(vector<Point>& points) 88 { 89 vector<Point> p = ConvexHull(points); 90 int n = p.size(); 91 if(n == 1) return 0; 92 if(n == 2) return Dist2(p[0], p[1]); 93 p.push_back(p[0]); // 免得取模 94 int ans = 0; 95 for(int u = 0, v = 1; u < n; u++) 96 { 97 // 一条直线贴住边p[u]-p[u+1] 98 for(;;) 99 { 100 // 当Area(p[u], p[u+1], p[v+1]) <= Area(p[u], p[u+1], p[v])时停止旋转 101 // 即Cross(p[u+1]-p[u], p[v+1]-p[u]) - Cross(p[u+1]-p[u], p[v]-p[u]) <= 0 102 // 根据Cross(A,B) - Cross(A,C) = Cross(A,B-C) 103 // 化简得Cross(p[u+1]-p[u], p[v+1]-p[v]) <= 0 104 int diff = Cross(p[u+1]-p[u], p[v+1]-p[v]); 105 if(diff <= 0) 106 { 107 ans = max(ans, Dist2(p[u], p[v])); // u和v是对踵点 108 if(diff == 0) ans = max(ans, Dist2(p[u], p[v+1])); // diff == 0时u和v+1也是对踵点 109 break; 110 } 111 v = (v + 1) % n; 112 } 113 } 114 return ans; 115 } 116 117 int main() 118 { 119 int T; 120 scanf("%d", &T); 121 while(T--) 122 { 123 int n; 124 scanf("%d", &n); 125 vector<Point> points; 126 for(int i = 0; i < n; i++) 127 { 128 int x, y, w; 129 scanf("%d%d%d", &x, &y, &w); 130 points.push_back(Point(x, y)); 131 points.push_back(Point(x+w, y)); 132 points.push_back(Point(x, y+w)); 133 points.push_back(Point(x+w, y+w)); 134 } 135 printf("%d\n", diameter2(points)); 136 } 137 return 0; 138 }
时间: 2024-10-05 16:42:17