uvalive 4728 Squares

题意:求所有正方形中两点距离最大值的平方值。

思路:旋转卡壳法。

分别用数组和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 }
View Code

 

posted @ 2015-10-17 12:49  yyblues  阅读(210)  评论(0编辑  收藏  举报