LA 4728 Squares (二维凸包+旋转卡壳)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4199

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=2729&mosmsg=Submission+received+with+ID+1236098

  依然是《训练指南》上面的题。这题题意是,给出一堆正方形区域,问区域中最远点对的距离的平方是多少。

  做法是经典的凸包加上旋转卡壳。因为正方形区域距离最大的两个点必然在凸包的顶点上,所以将正方形区域的四个顶点加入点集,然后构造二维位凸包。最后模拟旋转卡壳的做法就可以轻松通过这题了。旋转卡壳,按我的理解是模拟一条紧贴凸包的边的直线,然后找到离这条直线的最远点,这个点就是这条边上的对踵点了。1y~

代码如下:

View Code
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cmath>
  4 #include <set>
  5 #include <vector>
  6 #include <iostream>
  7 #include <algorithm>
  8 
  9 using namespace std;
 10 
 11 struct Point {
 12     double x, y;
 13     Point() {}
 14     Point(double x, double y) : x(x), y(y) {}
 15 } ;
 16 template<class T> T sqr(T x) { return x * x;}
 17 inline double ptDis(Point a, Point b) { return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));}
 18 
 19 // basic calculations
 20 typedef Point Vec;
 21 Vec operator + (Vec a, Vec b) { return Vec(a.x + b.x, a.y + b.y);}
 22 Vec operator - (Vec a, Vec b) { return Vec(a.x - b.x, a.y - b.y);}
 23 Vec operator * (Vec a, double p) { return Vec(a.x * p, a.y * p);}
 24 Vec operator / (Vec a, double p) { return Vec(a.x / p, a.y / p);}
 25 
 26 const double EPS = 5e-13;
 27 const double PI = acos(-1.0);
 28 inline int sgn(double x) { return fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1);}
 29 bool operator < (Point a, Point b) { return a.x < b.x || (a.x == b.x && a.y < b.y);}
 30 bool operator == (Point a, Point b) { return sgn(a.x - b.x) == 0 && sgn(a.y - b.y) == 0;}
 31 
 32 inline double dotDet(Vec a, Vec b) { return a.x * b.x + a.y * b.y;}
 33 inline double crossDet(Vec a, Vec b) { return a.x * b.y - a.y * b.x;}
 34 inline double crossDet(Point o, Point a, Point b) { return crossDet(a - o, b - o);}
 35 inline double vecLen(Vec x) { return sqrt(sqr(x.x) + sqr(x.y));}
 36 inline double toRad(double deg) { return deg / 180.0 * PI;}
 37 inline double angle(Vec v) { return atan2(v.y, v.x);}
 38 inline double angle(Vec a, Vec b) { return acos(dotDet(a, b) / vecLen(a) / vecLen(b));}
 39 inline double triArea(Point a, Point b, Point c) { return fabs(crossDet(b - a, c - a));}
 40 inline Vec vecUnit(Vec x) { return x / vecLen(x);}
 41 inline Vec rotate(Vec x, double rad) { return Vec(x.x * cos(rad) - x.y * sin(rad), x.x * sin(rad) + x.y * cos(rad));}
 42 Vec normal(Vec x) {
 43     double len = vecLen(x);
 44     return Vec(- x.y / len, x.x / len);
 45 }
 46 
 47 struct Line {
 48     Point s, t;
 49     Line() {}
 50     Line(Point s, Point t) : s(s), t(t) {}
 51     Point point(double x) {
 52         return s + (t - s) * x;
 53     }
 54     Line move(double x) {
 55         Vec nor = normal(t - s);
 56         nor = nor / vecLen(nor) * x;
 57         return Line(s + nor, t + nor);
 58     }
 59     Vec vec() { return t - s;}
 60 } ;
 61 typedef Line Seg;
 62 
 63 inline bool onSeg(Point x, Point a, Point b) { return sgn(crossDet(a - x, b - x)) == 0 && sgn(dotDet(a - x, b - x)) < 0;}
 64 inline bool onSeg(Point x, Seg s) { return onSeg(x, s.s, s.t);}
 65 
 66 // 0 : not intersect
 67 // 1 : proper intersect
 68 // 2 : improper intersect
 69 int segIntersect(Point a, Point c, Point b, Point d) {
 70     Vec v1 = b - a, v2 = c - b, v3 = d - c, v4 = a - d;
 71     int a_bc = sgn(crossDet(v1, v2));
 72     int b_cd = sgn(crossDet(v2, v3));
 73     int c_da = sgn(crossDet(v3, v4));
 74     int d_ab = sgn(crossDet(v4, v1));
 75     if (a_bc * c_da > 0 && b_cd * d_ab > 0) return 1;
 76     if (onSeg(b, a, c) && c_da) return 2;
 77     if (onSeg(c, b, d) && d_ab) return 2;
 78     if (onSeg(d, c, a) && a_bc) return 2;
 79     if (onSeg(a, d, b) && b_cd) return 2;
 80     return 0;
 81 }
 82 inline int segIntersect(Seg a, Seg b) { return segIntersect(a.s, a.t, b.s, b.t);}
 83 
 84 // point of the intersection of 2 lines
 85 Point lineIntersect(Point P, Vec v, Point Q, Vec w) {
 86     Vec u = P - Q;
 87     double t = crossDet(w, u) / crossDet(v, w);
 88     return P + v * t;
 89 }
 90 inline Point lineIntersect(Line a, Line b) { return lineIntersect(a.s, a.t - a.s, b.s, b.t - b.s);}
 91 
 92 // Warning: This is a DIRECTED Distance!!!
 93 double pt2Line(Point x, Point a, Point b) {
 94     Vec v1 = b - a, v2 = x - a;
 95     return crossDet(v1, v2) / vecLen(v1);
 96 }
 97 inline double pt2Line(Point x, Line L) { return pt2Line(x, L.s, L.t);}
 98 
 99 double pt2Seg(Point x, Point a, Point b) {
100     if (a == b) return vecLen(x - a);
101     Vec v1 = b - a, v2 = x - a, v3 = x - b;
102     if (sgn(dotDet(v1, v2)) < 0) return vecLen(v2);
103     if (sgn(dotDet(v1, v3)) > 0) return vecLen(v3);
104     return fabs(crossDet(v1, v2)) / vecLen(v1);
105 }
106 inline double pt2Seg(Point x, Seg s) { return pt2Seg(x, s.s, s.t);}
107 
108 struct Poly {
109     vector<Point> pt;
110     Poly() { pt.clear();}
111     Poly(vector<Point> pt) : pt(pt) {}
112     Point operator [] (int x) const { return pt[x];}
113     int size() { return pt.size();}
114     double area() {
115         double ret = 0.0;
116         int sz = pt.size();
117         for (int i = 1; i < sz; i++) {
118             ret += crossDet(pt[i], pt[i - 1]);
119         }
120         return fabs(ret / 2.0);
121     }
122 } ;
123 
124 struct Circle {
125     Point c;
126     double r;
127     Circle() {}
128     Circle(Point c, double r) : c(c), r(r) {}
129     Point point(double a) {
130         return Point(c.x + cos(a) * r, c.y + sin(a) * r);
131     }
132 } ;
133 
134 int lineCircleIntersect(Line L, Circle C, double &t1, double &t2, vector<Point> &sol) {
135     double a = L.s.x, b = L.t.x - C.c.x, c = L.s.y, d = L.t.y - C.c.y;
136     double e = sqr(a) + sqr(c), f = 2 * (a * b + c * d), g = sqr(b) + sqr(d) - sqr(C.r);
137     double delta = sqr(f) - 4.0 * e * g;
138     if (sgn(delta) < 0) return 0;
139     if (sgn(delta) == 0) {
140         t1 = t2 = -f / (2.0 * e);
141         sol.push_back(L.point(t1));
142         return 1;
143     }
144     t1 = (-f - sqrt(delta)) / (2.0 * e);
145     sol.push_back(L.point(t1));
146     t2 = (-f + sqrt(delta)) / (2.0 * e);
147     sol.push_back(L.point(t2));
148     return 2;
149 }
150 
151 int lineCircleIntersect(Line L, Circle C, vector<Point> &sol) {
152     Vec dir = L.t - L.s, nor = normal(dir);
153     Point mid = lineIntersect(C.c, nor, L.s, dir);
154     double len = sqr(C.r) - sqr(ptDis(C.c, mid));
155     if (sgn(len) < 0) return 0;
156     if (sgn(len) == 0) {
157         sol.push_back(mid);
158         return 1;
159     }
160     Vec dis = vecUnit(dir);
161     len = sqrt(len);
162     sol.push_back(mid + dis * len);
163     sol.push_back(mid - dis * len);
164     return 2;
165 }
166 
167 // -1 : coincide
168 int circleCircleIntersect(Circle C1, Circle C2, vector<Point> &sol) {
169     double d = vecLen(C1.c - C2.c);
170     if (sgn(d) == 0) {
171         if (sgn(C1.r - C2.r) == 0) {
172             return -1;
173         }
174         return 0;
175     }
176     if (sgn(C1.r + C2.r - d) < 0) return 0;
177     if (sgn(fabs(C1.r - C2.r) - d) > 0) return 0;
178     double a = angle(C2.c - C1.c);
179     double da = acos((sqr(C1.r) + sqr(d) - sqr(C2.r)) / (2.0 * C1.r * d));
180     Point p1 = C1.point(a - da), p2 = C1.point(a + da);
181     sol.push_back(p1);
182     if (p1 == p2) return 1;
183     sol.push_back(p2);
184     return 2;
185 }
186 
187 void circleCircleIntersect(Circle C1, Circle C2, vector<double> &sol) {
188     double d = vecLen(C1.c - C2.c);
189     if (sgn(d) == 0) return ;
190     if (sgn(C1.r + C2.r - d) < 0) return ;
191     if (sgn(fabs(C1.r - C2.r) - d) > 0) return ;
192     double a = angle(C2.c - C1.c);
193     double da = acos((sqr(C1.r) + sqr(d) - sqr(C2.r)) / (2.0 * C1.r * d));
194     sol.push_back(a - da);
195     sol.push_back(a + da);
196 }
197 
198 int tangent(Point p, Circle C, vector<Vec> &sol) {
199     Vec u = C.c - p;
200     double dist = vecLen(u);
201     if (dist < C.r) return 0;
202     if (sgn(dist - C.r) == 0) {
203         sol.push_back(rotate(u, PI / 2.0));
204         return 1;
205     }
206     double ang = asin(C.r / dist);
207     sol.push_back(rotate(u, -ang));
208     sol.push_back(rotate(u, ang));
209     return 2;
210 }
211 
212 // ptA : points of tangency on circle A
213 // ptB : points of tangency on circle B
214 int tangent(Circle A, Circle B, vector<Point> &ptA, vector<Point> &ptB) {
215     if (A.r < B.r) {
216         swap(A, B);
217         swap(ptA, ptB);
218     }
219     int d2 = sqr(A.c.x - B.c.x) + sqr(A.c.y - B.c.y);
220     int rdiff = A.r - B.r, rsum = A.r + B.r;
221     if (d2 < sqr(rdiff)) return 0;
222     double base = atan2(B.c.y - A.c.y, B.c.x - A.c.x);
223     if (d2 == 0 && A.r == B.r) return -1;
224     if (d2 == sqr(rdiff)) {
225         ptA.push_back(A.point(base));
226         ptB.push_back(B.point(base));
227         return 1;
228     }
229     double ang = acos((A.r - B.r) / sqrt(d2));
230     ptA.push_back(A.point(base + ang));
231     ptB.push_back(B.point(base + ang));
232     ptA.push_back(A.point(base - ang));
233     ptB.push_back(B.point(base - ang));
234     if (d2 == sqr(rsum)) {
235         ptA.push_back(A.point(base));
236         ptB.push_back(B.point(PI + base));
237     } else if (d2 > sqr(rsum)) {
238         ang = acos((A.r + B.r) / sqrt(d2));
239         ptA.push_back(A.point(base + ang));
240         ptB.push_back(B.point(PI + base + ang));
241         ptA.push_back(A.point(base - ang));
242         ptB.push_back(B.point(PI + base - ang));
243     }
244     return (int) ptA.size();
245 }
246 
247 void getCoor(double R, double lat, double lng, double &x, double &y, double &z) {
248     lat = toRad(lat);
249     lng = toRad(lng);
250     x = R * cos(lat) * cos(lng);
251     y = R * cos(lat) * sin(lng);
252     z = R * sin(lat);
253 }
254 
255 // -1 : onside
256 // 0 : outside
257 // 1 : inside
258 int ptInPoly(Point p, Poly poly) {
259     int wn = 0, sz = poly.size();
260     for (int i = 0; i < sz; i++) {
261         if (onSeg(p, poly[i], poly[(i + 1) % sz])) return -1;
262         int k = sgn(crossDet(poly[(i + 1) % sz] - poly[i], p - poly[i]));
263         int d1 = sgn(poly[i].y - p.y);
264         int d2 = sgn(poly[(i + 1) % sz].y - p.y);
265         if (k > 0 && d1 <= 0 && d2 > 0) wn++;
266         if (k < 0 && d2 <= 0 && d1 > 0) wn--;
267     }
268     if (wn != 0) return 1;
269     return 0;
270 }
271 
272 // if DO NOT need a high precision
273 /*
274 int ptInPoly(Point p, Poly poly) {
275     int sz = poly.size();
276     double ang = 0.0, tmp;
277     for (int i = 0; i < sz; i++) {
278         if (onSeg(p, poly[i], poly[(i + 1) % sz])) return -1;
279         tmp = angle(poly[i] - p) - angle(poly[(i + 1) % sz] - p) + PI;
280         ang += tmp - floor(tmp / (2.0 * PI)) * 2.0 * PI - PI;
281     }
282     if (sgn(ang - PI) == 0) return -1;
283     if (sgn(ang) == 0) return 0;
284     return 1;
285 }
286 */
287 
288 // convex hull algorithms
289 // return the number of points in convex hull
290 
291 // andwer's algorithm
292 // if DO NOT want the points on the side of convex hull, change all "<" into "<="
293 int andrew(Point *pt, int n, Point *ch) {
294     sort(pt, pt + n);
295     int m = 0;
296     for (int i = 0; i < n; i++) {
297         while (m > 1 && crossDet(ch[m - 1] - ch[m - 2], pt[i] - ch[m - 2]) <= 0) m--;
298         ch[m++] = pt[i];
299     }
300     int k = m;
301     for (int i = n - 2; i >= 0; i--) {
302         while (m > k && crossDet(ch[m - 1] - ch[m - 2], pt[i] - ch[m - 2]) <= 0) m--;
303         ch[m++] = pt[i];
304     }
305     if (n > 1) m--;
306     return m;
307 }
308 
309 // graham's algorithm
310 // if DO NOT want the points on the side of convex hull, change all "<=" into "<"
311 Point origin;
312 inline bool cmpAng(Point p1, Point p2) { return crossDet(origin, p1, p2) > 0;}
313 inline bool cmpDis(Point p1, Point p2) { return ptDis(p1, origin) > ptDis(p2, origin);}
314 
315 void removePt(Point *pt, int &n) {
316     int idx = 1;
317     for (int i = 2; i < n; i++) {
318         if (sgn(crossDet(origin, pt[i], pt[idx]))) pt[++idx] = pt[i];
319         else if (cmpDis(pt[i], pt[idx])) pt[idx] = pt[i];
320     }
321     n = idx + 1;
322 }
323 
324 int graham(Point *pt, int n, Point *ch) {
325     int top = -1;
326     for (int i = 1; i < n; i++) {
327         if (pt[i].y < pt[0].y || (pt[i].y == pt[0].y && pt[i].x < pt[0].x)) swap(pt[i], pt[0]);
328     }
329     origin = pt[0];
330     sort(pt + 1, pt + n, cmpAng);
331     removePt(pt, n);
332     for (int i = 0; i < n; i++) {
333         if (i >= 2) {
334             while (!(crossDet(ch[top - 1], pt[i], ch[top]) <= 0)) top--;
335         }
336         ch[++top] = pt[i];
337     }
338     return top + 1;
339 }
340 
341 /****************** template above *******************/
342 
343 #define REP(i, n) for (int i = 0; i < (n); i++)
344 #define REP_1(i, n) for (int i = 1; i <= (n); i++)
345 
346 inline int nextID(int x, int n) { return (x + 1) % n;}
347 
348 double diameter(Point *pt, int n) {
349     double ret = 0.0;
350     int top = 0;
351     REP(i, n) {
352         while (pt2Line(pt[top], pt[i], pt[i + 1]) <= pt2Line(pt[nextID(top, n)], pt[i], pt[i + 1])) {
353             ret = max(ret, max(ptDis(pt[top], pt[i]), ptDis(pt[top], pt[i + 1])));
354             top = nextID(top, n);
355         }
356         ret = max(ret, max(ptDis(pt[top], pt[i]), ptDis(pt[top], pt[i + 1])));
357     }
358     return ret;
359 }
360 
361 const int N = 444444;
362 Point pt[N], con[N];
363 const int dir[4][2] = { {0, 0}, {1, 0}, {0, 1}, {1, 1}};
364 
365 int main() {
366 //    freopen("in", "r", stdin);
367     int n, T;
368     scanf("%d", &T);
369     while (T-- && ~scanf("%d", &n)) {
370         double x, y, w;
371         REP(i, n) {
372             scanf("%lf%lf%lf", &x, &y, &w);
373             REP(j, 4) {
374                 pt[(i << 2) + j] = Point(x + w * dir[j][0], y + w * dir[j][1]);
375             }
376         }
377         n = andrew(pt, n << 2, con);
378         con[n] = con[0];
379         printf("%.0f\n", sqr(diameter(con, n)));
380     }
381     return 0;
382 }

 

稍微精简点的代码,总觉得会有bug,不过最后还是过了:

View Code
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cmath>
  4 #include <set>
  5 #include <vector>
  6 #include <iostream>
  7 #include <algorithm>
  8 
  9 using namespace std;
 10 
 11 struct Point {
 12     double x, y;
 13     Point() {}
 14     Point(double x, double y) : x(x), y(y) {}
 15 } ;
 16 template<class T> T sqr(T x) { return x * x;}
 17 inline double ptDis(Point a, Point b) { return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));}
 18 
 19 // basic calculations
 20 typedef Point Vec;
 21 Vec operator + (Vec a, Vec b) { return Vec(a.x + b.x, a.y + b.y);}
 22 Vec operator - (Vec a, Vec b) { return Vec(a.x - b.x, a.y - b.y);}
 23 Vec operator * (Vec a, double p) { return Vec(a.x * p, a.y * p);}
 24 Vec operator / (Vec a, double p) { return Vec(a.x / p, a.y / p);}
 25 
 26 const double EPS = 5e-13;
 27 const double PI = acos(-1.0);
 28 inline int sgn(double x) { return fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1);}
 29 bool operator < (Point a, Point b) { return a.x < b.x || (a.x == b.x && a.y < b.y);}
 30 bool operator == (Point a, Point b) { return sgn(a.x - b.x) == 0 && sgn(a.y - b.y) == 0;}
 31 
 32 inline double dotDet(Vec a, Vec b) { return a.x * b.x + a.y * b.y;}
 33 inline double crossDet(Vec a, Vec b) { return a.x * b.y - a.y * b.x;}
 34 inline double crossDet(Point o, Point a, Point b) { return crossDet(a - o, b - o);}
 35 inline double vecLen(Vec x) { return sqrt(sqr(x.x) + sqr(x.y));}
 36 inline double toRad(double deg) { return deg / 180.0 * PI;}
 37 inline double angle(Vec v) { return atan2(v.y, v.x);}
 38 inline double angle(Vec a, Vec b) { return acos(dotDet(a, b) / vecLen(a) / vecLen(b));}
 39 inline double triArea(Point a, Point b, Point c) { return fabs(crossDet(b - a, c - a));}
 40 inline Vec vecUnit(Vec x) { return x / vecLen(x);}
 41 inline Vec rotate(Vec x, double rad) { return Vec(x.x * cos(rad) - x.y * sin(rad), x.x * sin(rad) + x.y * cos(rad));}
 42 Vec normal(Vec x) {
 43     double len = vecLen(x);
 44     return Vec(- x.y / len, x.x / len);
 45 }
 46 
 47 struct Line {
 48     Point s, t;
 49     Line() {}
 50     Line(Point s, Point t) : s(s), t(t) {}
 51     Point point(double x) {
 52         return s + (t - s) * x;
 53     }
 54     Line move(double x) {
 55         Vec nor = normal(t - s);
 56         nor = nor / vecLen(nor) * x;
 57         return Line(s + nor, t + nor);
 58     }
 59     Vec vec() { return t - s;}
 60 } ;
 61 typedef Line Seg;
 62 
 63 inline bool onSeg(Point x, Point a, Point b) { return sgn(crossDet(a - x, b - x)) == 0 && sgn(dotDet(a - x, b - x)) < 0;}
 64 inline bool onSeg(Point x, Seg s) { return onSeg(x, s.s, s.t);}
 65 
 66 // 0 : not intersect
 67 // 1 : proper intersect
 68 // 2 : improper intersect
 69 int segIntersect(Point a, Point c, Point b, Point d) {
 70     Vec v1 = b - a, v2 = c - b, v3 = d - c, v4 = a - d;
 71     int a_bc = sgn(crossDet(v1, v2));
 72     int b_cd = sgn(crossDet(v2, v3));
 73     int c_da = sgn(crossDet(v3, v4));
 74     int d_ab = sgn(crossDet(v4, v1));
 75     if (a_bc * c_da > 0 && b_cd * d_ab > 0) return 1;
 76     if (onSeg(b, a, c) && c_da) return 2;
 77     if (onSeg(c, b, d) && d_ab) return 2;
 78     if (onSeg(d, c, a) && a_bc) return 2;
 79     if (onSeg(a, d, b) && b_cd) return 2;
 80     return 0;
 81 }
 82 inline int segIntersect(Seg a, Seg b) { return segIntersect(a.s, a.t, b.s, b.t);}
 83 
 84 // point of the intersection of 2 lines
 85 Point lineIntersect(Point P, Vec v, Point Q, Vec w) {
 86     Vec u = P - Q;
 87     double t = crossDet(w, u) / crossDet(v, w);
 88     return P + v * t;
 89 }
 90 inline Point lineIntersect(Line a, Line b) { return lineIntersect(a.s, a.t - a.s, b.s, b.t - b.s);}
 91 
 92 // Warning: This is a DIRECTED Distance!!!
 93 double pt2Line(Point x, Point a, Point b) {
 94     Vec v1 = b - a, v2 = x - a;
 95     return crossDet(v1, v2) / vecLen(v1);
 96 }
 97 inline double pt2Line(Point x, Line L) { return pt2Line(x, L.s, L.t);}
 98 
 99 double pt2Seg(Point x, Point a, Point b) {
100     if (a == b) return vecLen(x - a);
101     Vec v1 = b - a, v2 = x - a, v3 = x - b;
102     if (sgn(dotDet(v1, v2)) < 0) return vecLen(v2);
103     if (sgn(dotDet(v1, v3)) > 0) return vecLen(v3);
104     return fabs(crossDet(v1, v2)) / vecLen(v1);
105 }
106 inline double pt2Seg(Point x, Seg s) { return pt2Seg(x, s.s, s.t);}
107 
108 struct Poly {
109     vector<Point> pt;
110     Poly() { pt.clear();}
111     Poly(vector<Point> pt) : pt(pt) {}
112     Point operator [] (int x) const { return pt[x];}
113     int size() { return pt.size();}
114     double area() {
115         double ret = 0.0;
116         int sz = pt.size();
117         for (int i = 1; i < sz; i++) {
118             ret += crossDet(pt[i], pt[i - 1]);
119         }
120         return fabs(ret / 2.0);
121     }
122 } ;
123 
124 struct Circle {
125     Point c;
126     double r;
127     Circle() {}
128     Circle(Point c, double r) : c(c), r(r) {}
129     Point point(double a) {
130         return Point(c.x + cos(a) * r, c.y + sin(a) * r);
131     }
132 } ;
133 
134 int lineCircleIntersect(Line L, Circle C, double &t1, double &t2, vector<Point> &sol) {
135     double a = L.s.x, b = L.t.x - C.c.x, c = L.s.y, d = L.t.y - C.c.y;
136     double e = sqr(a) + sqr(c), f = 2 * (a * b + c * d), g = sqr(b) + sqr(d) - sqr(C.r);
137     double delta = sqr(f) - 4.0 * e * g;
138     if (sgn(delta) < 0) return 0;
139     if (sgn(delta) == 0) {
140         t1 = t2 = -f / (2.0 * e);
141         sol.push_back(L.point(t1));
142         return 1;
143     }
144     t1 = (-f - sqrt(delta)) / (2.0 * e);
145     sol.push_back(L.point(t1));
146     t2 = (-f + sqrt(delta)) / (2.0 * e);
147     sol.push_back(L.point(t2));
148     return 2;
149 }
150 
151 int lineCircleIntersect(Line L, Circle C, vector<Point> &sol) {
152     Vec dir = L.t - L.s, nor = normal(dir);
153     Point mid = lineIntersect(C.c, nor, L.s, dir);
154     double len = sqr(C.r) - sqr(ptDis(C.c, mid));
155     if (sgn(len) < 0) return 0;
156     if (sgn(len) == 0) {
157         sol.push_back(mid);
158         return 1;
159     }
160     Vec dis = vecUnit(dir);
161     len = sqrt(len);
162     sol.push_back(mid + dis * len);
163     sol.push_back(mid - dis * len);
164     return 2;
165 }
166 
167 // -1 : coincide
168 int circleCircleIntersect(Circle C1, Circle C2, vector<Point> &sol) {
169     double d = vecLen(C1.c - C2.c);
170     if (sgn(d) == 0) {
171         if (sgn(C1.r - C2.r) == 0) {
172             return -1;
173         }
174         return 0;
175     }
176     if (sgn(C1.r + C2.r - d) < 0) return 0;
177     if (sgn(fabs(C1.r - C2.r) - d) > 0) return 0;
178     double a = angle(C2.c - C1.c);
179     double da = acos((sqr(C1.r) + sqr(d) - sqr(C2.r)) / (2.0 * C1.r * d));
180     Point p1 = C1.point(a - da), p2 = C1.point(a + da);
181     sol.push_back(p1);
182     if (p1 == p2) return 1;
183     sol.push_back(p2);
184     return 2;
185 }
186 
187 void circleCircleIntersect(Circle C1, Circle C2, vector<double> &sol) {
188     double d = vecLen(C1.c - C2.c);
189     if (sgn(d) == 0) return ;
190     if (sgn(C1.r + C2.r - d) < 0) return ;
191     if (sgn(fabs(C1.r - C2.r) - d) > 0) return ;
192     double a = angle(C2.c - C1.c);
193     double da = acos((sqr(C1.r) + sqr(d) - sqr(C2.r)) / (2.0 * C1.r * d));
194     sol.push_back(a - da);
195     sol.push_back(a + da);
196 }
197 
198 int tangent(Point p, Circle C, vector<Vec> &sol) {
199     Vec u = C.c - p;
200     double dist = vecLen(u);
201     if (dist < C.r) return 0;
202     if (sgn(dist - C.r) == 0) {
203         sol.push_back(rotate(u, PI / 2.0));
204         return 1;
205     }
206     double ang = asin(C.r / dist);
207     sol.push_back(rotate(u, -ang));
208     sol.push_back(rotate(u, ang));
209     return 2;
210 }
211 
212 // ptA : points of tangency on circle A
213 // ptB : points of tangency on circle B
214 int tangent(Circle A, Circle B, vector<Point> &ptA, vector<Point> &ptB) {
215     if (A.r < B.r) {
216         swap(A, B);
217         swap(ptA, ptB);
218     }
219     int d2 = sqr(A.c.x - B.c.x) + sqr(A.c.y - B.c.y);
220     int rdiff = A.r - B.r, rsum = A.r + B.r;
221     if (d2 < sqr(rdiff)) return 0;
222     double base = atan2(B.c.y - A.c.y, B.c.x - A.c.x);
223     if (d2 == 0 && A.r == B.r) return -1;
224     if (d2 == sqr(rdiff)) {
225         ptA.push_back(A.point(base));
226         ptB.push_back(B.point(base));
227         return 1;
228     }
229     double ang = acos((A.r - B.r) / sqrt(d2));
230     ptA.push_back(A.point(base + ang));
231     ptB.push_back(B.point(base + ang));
232     ptA.push_back(A.point(base - ang));
233     ptB.push_back(B.point(base - ang));
234     if (d2 == sqr(rsum)) {
235         ptA.push_back(A.point(base));
236         ptB.push_back(B.point(PI + base));
237     } else if (d2 > sqr(rsum)) {
238         ang = acos((A.r + B.r) / sqrt(d2));
239         ptA.push_back(A.point(base + ang));
240         ptB.push_back(B.point(PI + base + ang));
241         ptA.push_back(A.point(base - ang));
242         ptB.push_back(B.point(PI + base - ang));
243     }
244     return (int) ptA.size();
245 }
246 
247 void getCoor(double R, double lat, double lng, double &x, double &y, double &z) {
248     lat = toRad(lat);
249     lng = toRad(lng);
250     x = R * cos(lat) * cos(lng);
251     y = R * cos(lat) * sin(lng);
252     z = R * sin(lat);
253 }
254 
255 // -1 : onside
256 // 0 : outside
257 // 1 : inside
258 int ptInPoly(Point p, Poly poly) {
259     int wn = 0, sz = poly.size();
260     for (int i = 0; i < sz; i++) {
261         if (onSeg(p, poly[i], poly[(i + 1) % sz])) return -1;
262         int k = sgn(crossDet(poly[(i + 1) % sz] - poly[i], p - poly[i]));
263         int d1 = sgn(poly[i].y - p.y);
264         int d2 = sgn(poly[(i + 1) % sz].y - p.y);
265         if (k > 0 && d1 <= 0 && d2 > 0) wn++;
266         if (k < 0 && d2 <= 0 && d1 > 0) wn--;
267     }
268     if (wn != 0) return 1;
269     return 0;
270 }
271 
272 // if DO NOT need a high precision
273 /*
274 int ptInPoly(Point p, Poly poly) {
275     int sz = poly.size();
276     double ang = 0.0, tmp;
277     for (int i = 0; i < sz; i++) {
278         if (onSeg(p, poly[i], poly[(i + 1) % sz])) return -1;
279         tmp = angle(poly[i] - p) - angle(poly[(i + 1) % sz] - p) + PI;
280         ang += tmp - floor(tmp / (2.0 * PI)) * 2.0 * PI - PI;
281     }
282     if (sgn(ang - PI) == 0) return -1;
283     if (sgn(ang) == 0) return 0;
284     return 1;
285 }
286 */
287 
288 // convex hull algorithms
289 // return the number of points in convex hull
290 
291 // andwer's algorithm
292 // if DO NOT want the points on the side of convex hull, change all "<" into "<="
293 int andrew(Point *pt, int n, Point *ch) {
294     sort(pt, pt + n);
295     int m = 0;
296     for (int i = 0; i < n; i++) {
297         while (m > 1 && crossDet(ch[m - 1] - ch[m - 2], pt[i] - ch[m - 2]) <= 0) m--;
298         ch[m++] = pt[i];
299     }
300     int k = m;
301     for (int i = n - 2; i >= 0; i--) {
302         while (m > k && crossDet(ch[m - 1] - ch[m - 2], pt[i] - ch[m - 2]) <= 0) m--;
303         ch[m++] = pt[i];
304     }
305     if (n > 1) m--;
306     return m;
307 }
308 
309 // graham's algorithm
310 // if DO NOT want the points on the side of convex hull, change all "<=" into "<"
311 Point origin;
312 inline bool cmpAng(Point p1, Point p2) { return crossDet(origin, p1, p2) > 0;}
313 inline bool cmpDis(Point p1, Point p2) { return ptDis(p1, origin) > ptDis(p2, origin);}
314 
315 void removePt(Point *pt, int &n) {
316     int idx = 1;
317     for (int i = 2; i < n; i++) {
318         if (sgn(crossDet(origin, pt[i], pt[idx]))) pt[++idx] = pt[i];
319         else if (cmpDis(pt[i], pt[idx])) pt[idx] = pt[i];
320     }
321     n = idx + 1;
322 }
323 
324 int graham(Point *pt, int n, Point *ch) {
325     int top = -1;
326     for (int i = 1; i < n; i++) {
327         if (pt[i].y < pt[0].y || (pt[i].y == pt[0].y && pt[i].x < pt[0].x)) swap(pt[i], pt[0]);
328     }
329     origin = pt[0];
330     sort(pt + 1, pt + n, cmpAng);
331     removePt(pt, n);
332     for (int i = 0; i < n; i++) {
333         if (i >= 2) {
334             while (!(crossDet(ch[top - 1], pt[i], ch[top]) <= 0)) top--;
335         }
336         ch[++top] = pt[i];
337     }
338     return top + 1;
339 }
340 
341 /****************** template above *******************/
342 
343 #define REP(i, n) for (int i = 0; i < (n); i++)
344 #define REP_1(i, n) for (int i = 1; i <= (n); i++)
345 
346 inline int nextID(int x, int n) { return (x + 1) % n;}
347 
348 double diameter(Point *pt, int n) {
349     double ret = 0.0;
350     int top = 0;
351     REP(i, n) {
352         while (pt2Line(pt[top], pt[i], pt[i + 1]) <= pt2Line(pt[nextID(top, n)], pt[i], pt[i + 1])) {
353 //            ret = max(ret, max(ptDis(pt[top], pt[i]), ptDis(pt[top], pt[i + 1])));
354             top = nextID(top, n);
355         }
356         ret = max(ret, max(ptDis(pt[top], pt[i]), ptDis(pt[top], pt[i + 1])));
357     }
358     return ret;
359 }
360 
361 const int N = 444444;
362 Point pt[N], con[N];
363 const int dir[4][2] = { {0, 0}, {1, 0}, {0, 1}, {1, 1}};
364 
365 int main() {
366 //    freopen("in", "r", stdin);
367     int n, T;
368     scanf("%d", &T);
369     while (T-- && ~scanf("%d", &n)) {
370         double x, y, w;
371         REP(i, n) {
372             scanf("%lf%lf%lf", &x, &y, &w);
373             REP(j, 4) {
374                 pt[(i << 2) + j] = Point(x + w * dir[j][0], y + w * dir[j][1]);
375             }
376         }
377         n = andrew(pt, n << 2, con);
378         con[n] = con[0];
379         printf("%.0f\n", sqr(diameter(con, n)));
380     }
381     return 0;
382 }

 

 

——written by Lyon

 

转载于:https://www.cnblogs.com/LyonLys/archive/2013/05/07/LA_4728_Lyon.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android是一种基于Linux内核(不包含GNU组件)的自由及开放源代码的移动操作系统,主要应用于移动设备,如智能手机和平板电脑。该系统最初由安迪·鲁宾开发,后被Google公司收购并注资,随后与多家硬件制造商、软件开发商及电信营运商共同研发改良。 Android操作系统的特点包括: 开放源代码:Android系统采用开放源代码模式,允许开发者自由访问、修改和定制操作系统,这促进了技术的创新和发展,使得Android系统具有高度的灵活性和可定制性。 多任务处理:Android允许用户同时运行多个应用程序,并且可以轻松地在不同应用程序之间切换,提高了效率和便利性。 丰富的应用生态系统:Android系统拥有庞大的应用程序生态系统,用户可以从Google Play商店或其他第三方应用市场下载和安装各种各样的应用程序,满足各种需求。 可定制性:Android操作系统可以根据用户的个人喜好进行定制,用户可以更改主题、小部件和图标等,以使其界面更符合个人风格和偏好。 多种设备支持:Android操作系统可以运行在多种不同类型的设备上,包括手机、平板电脑、智能电视、汽车导航系统等。 此外,Android系统还有一些常见的问题,如应用崩溃、电池耗电过快、Wi-Fi连接问题、存储空间不足、更新问题等。针对这些问题,用户可以尝试一些基本的解决方法,如清除应用缓存和数据、降低屏幕亮度、关闭没有使用的连接和传感器、限制后台运行的应用、删除不需要的文件和应用等。 随着Android系统的不断发展,其功能和性能也在不断提升。例如,最新的Android版本引入了更多的安全性和隐私保护功能,以及更流畅的用户界面和更强大的性能。此外,Android系统也在不断探索新的应用场景,如智能家居、虚拟现实、人工智能等领域。 总之,Android系统是一种功能强大、灵活可定制、拥有丰富应用生态系统的移动操作系统,在全球范围内拥有广泛的用户基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值