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
", rotating_calipers(p, top));
143     }
144     return 0;
145 }
原文地址:https://www.cnblogs.com/langyao/p/8962727.html