poj2187 Beauty Contest(旋转卡壳)

转载请注明出处: http://www.cnblogs.com/fraud/           ——by fraud

Beauty Contest
Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 31214   Accepted: 9681

Description

Bessie, Farmer John's prize cow, has just won first place in a bovine beauty contest, earning the title 'Miss Cow World'. As a result, Bessie will make a tour of N (2 <= N <= 50,000) farms around the world in order to spread goodwill between farmers and their cows. For simplicity, the world will be represented as a two-dimensional plane, where each farm is located at a pair of integer coordinates (x,y), each having a value in the range -10,000 ... 10,000. No two farms share the same pair of coordinates. 

Even though Bessie travels directly in a straight line between pairs of farms, the distance between some farms can be quite large, so she wants to bring a suitcase full of hay with her so she has enough food to eat on each leg of her journey. Since Bessie refills her suitcase at every farm she visits, she wants to determine the maximum possible distance she might need to travel so she knows the size of suitcase she must bring.Help Bessie by computing the maximum distance among all pairs of farms. 

Input

* Line 1: A single integer, N 

* Lines 2..N+1: Two space-separated integers x and y specifying coordinate of each farm 

Output

* Line 1: A single integer that is the squared distance between the pair of farms that are farthest apart from each other. 

Sample Input

4
0 0
0 1
1 1
1 0

Sample Output

2

Hint

Farm 1 (0, 0) and farm 3 (1, 1) have the longest distance (square root of 2) 

求平面的最远点对。

由于点的范围在-10000到10000之间,所以取完凸包后,凸包上的点的数目并不会很多,不会超过根号M个,所以可以求完凸包之后直接暴力枚举凸包上的点来做。

  1 /**
  2  * code generated by JHelper
  3  * More info: https://github.com/AlexeyDmitriev/JHelper
  4  * @author xyiyy @https://github.com/xyiyy
  5  */
  6 
  7 #include <iostream>
  8 #include <fstream>
  9 
 10 //#####################
 11 //Author:fraud
 12 //Blog: http://www.cnblogs.com/fraud/
 13 //#####################
 14 //#pragma comment(linker, "/STACK:102400000,102400000")
 15 #include <iostream>
 16 #include <sstream>
 17 #include <ios>
 18 #include <iomanip>
 19 #include <functional>
 20 #include <algorithm>
 21 #include <vector>
 22 #include <string>
 23 #include <list>
 24 #include <queue>
 25 #include <deque>
 26 #include <stack>
 27 #include <set>
 28 #include <map>
 29 #include <cstdio>
 30 #include <cstdlib>
 31 #include <cmath>
 32 #include <cstring>
 33 #include <climits>
 34 #include <cctype>
 35 
 36 using namespace std;
 37 #define rep(X, N) for(int X=0;X<N;X++)
 38 
 39 const double EPS = 1e-10;
 40 
 41 double add(double a, double b) {
 42     if (abs(a + b) < EPS * (abs(a) + abs(b)))return 0;
 43     return a + b;
 44 }
 45 
 46 struct P {
 47     double x, y;
 48 
 49     P() { }
 50 
 51     P(double x, double y) : x(x), y(y) { }
 52 
 53     P operator+(P p) {
 54         return P(add(x, p.x), add(y, p.y));
 55     }
 56 
 57     P operator-(P p) {
 58         return P(add(x, -p.x), add(y, -p.y));
 59     }
 60 
 61     double dot(P p) {
 62         return add(x * p.x, y * p.y);
 63     }
 64 
 65     double det(P p) {
 66         return add(x * p.y, -y * p.x);
 67     }
 68 };
 69 
 70 double dist(P p, P q) {
 71     return (p - q).dot(p - q);
 72 }
 73 
 74 bool cmp_x(const P &p, const P &q) {
 75     if (p.x != q.x)return p.x < q.x;
 76     return p.y < q.y;
 77 }
 78 
 79 vector<P> convex_hull(P *ps, int n) {
 80     sort(ps, ps + n, cmp_x);
 81     int k = 0;
 82     vector<P> qs(n * 2);
 83     for (int i = 0; i < n; qs[k++] = ps[i++]) {
 84         while (k > 1 && (qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]) < EPS)k--;
 85     }
 86     for (int i = n - 2, t = k; i >= 0; qs[k++] = ps[i--]) {
 87         while (k > t && (qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]) < EPS)k--;
 88     }
 89     qs.resize(k - 1);
 90     return qs;
 91 }
 92 
 93 const int MAXN = 50010;
 94 
 95 class poj2187 {
 96 public:
 97     void solve() {
 98         int n;
 99         scanf("%d",&n);//in >> n;
100         P *ps = new P[MAXN];
101         rep(i, n) {
102             scanf("%lf%lf",&ps[i].x,&ps[i].y);//in >> ps[i].x >> ps[i].y;
103         }
104         vector<P> qs = convex_hull(ps, n);
105         double res = 0;
106         rep(i, qs.size()) {
107             rep(j, i) {
108                 res = max(res, dist(qs[i], qs[j]));
109             }
110         }
111          printf("%.0f\n",res);
112         //out << fixed << setprecision(0) << res << endl;
113     }
114 };
115 
116 int main() {
117     //std::ios::sync_with_stdio(false);
118     //std::cin.tie(0);
119     poj2187 solver;
120     //std::istream &in(std::cin);
121    // std::ostream &out(std::cout);
122     solver.solve();
123     return 0;
124 }
代码君

对于凸包上最远的两个点,其实可以使用旋转卡壳来做,其实旋转卡壳的思想是比较容易理解的,首先找到对踵点对,

不明白的可以先看一下以下链接

https://en.wikipedia.org/wiki/Rotating_calipers

然后在考虑转移的情况,在凸包上,对于一个点和其他所有点的距离,绕一圈,正好构成一个单峰函数,那么,对踵点对就一定是在变小的那个地方,所以这样想通后只要找出所有的对踵点对间距离的最大值,这样原来需要在凸包上枚举所有点的O(n^2)的方法就可以通过旋转卡壳改进成O(n)了,外加上前面求凸包O(nlogn)的复杂度,这道题就可以轻松切掉了。

下面附上C++版和Java版的代码

C++:

  1 /**
  2  * code generated by JHelper
  3  * More info: https://github.com/AlexeyDmitriev/JHelper
  4  * @author xyiyy @https://github.com/xyiyy
  5  */
  6 
  7 #include <iostream>
  8 #include <fstream>
  9 
 10 //#####################
 11 //Author:fraud
 12 //Blog: http://www.cnblogs.com/fraud/
 13 //#####################
 14 //#pragma comment(linker, "/STACK:102400000,102400000")
 15 #include <iostream>
 16 #include <sstream>
 17 #include <ios>
 18 #include <iomanip>
 19 #include <functional>
 20 #include <algorithm>
 21 #include <vector>
 22 #include <string>
 23 #include <list>
 24 #include <queue>
 25 #include <deque>
 26 #include <stack>
 27 #include <set>
 28 #include <map>
 29 #include <cstdio>
 30 #include <cstdlib>
 31 #include <cmath>
 32 #include <cstring>
 33 #include <climits>
 34 #include <cctype>
 35 
 36 using namespace std;
 37 #define rep(X, N) for(int X=0;X<N;X++)
 38 
 39 //
 40 // Created by xyiyy on 2015/8/10.
 41 //
 42 
 43 #ifndef JHELPER_EXAMPLE_PROJECT_P_HPP
 44 #define JHELPER_EXAMPLE_PROJECT_P_HPP
 45 
 46 const double EPS = 1e-9;
 47 
 48 double add(double a, double b) {
 49     if (fabs(a + b) < EPS * (fabs(a) + fabs(b)))return 0;
 50     return a + b;
 51 }
 52 
 53 class P {
 54 public:
 55     double x, y;
 56     P() {}
 57     P(double x, double y):x(x),y(y){}
 58 
 59 
 60     P  operator+(const P &p) {
 61         return P(add(x, p.x), add(y, p.y));
 62     }
 63 
 64     P operator-(const P &p) {
 65         return P(add(x, -p.x), add(y, -p.y));
 66     }
 67 
 68     P operator*(const double &d) {
 69         return P(x * d, y * d);
 70     }
 71 
 72     P operator/(const double &d) {
 73         return P(x / d, y / d);
 74     }
 75 
 76     double dot(P p) {
 77         return add(x * p.x, y * p.y);
 78     }
 79 
 80     double det(P p) {
 81         return add(x * p.y, -y * p.x);
 82     }
 83 
 84 
 85     double abs() {
 86         return sqrt(abs2());
 87     }
 88 
 89     double abs2() {
 90         return dot(*this);
 91     }
 92 
 93 };
 94 
 95 
 96 
 97 //直线和直线的交点
 98 /*P isLL(P p1,P p2,P q1,P q2){
 99     double d = (q2 - q1).det(p2 - p1);
100     if(sig(d)==0)return NULL;
101     return intersection(p1,p2,q1,q2);
102 }*/
103 
104 
105 //四点共圆判定
106 /*bool onC(P p1,P p2,P p3,P p4){
107     P c = CCenter(p1,p2,p3);
108     if(c == NULL) return false;
109     return add((c - p1).abs2(), -(c - p4).abs2()) == 0;
110 }*/
111 
112 //三点共圆的圆心
113 /*P CCenter(P p1,P p2,P p3){
114     //if(disLP(p1, p2, p3) < EPS)return NULL;//三点共线
115     P q1 = (p1 + p2) * 0.5;
116     P q2 = q1 + ((p1 - p2).rot90());
117     P s1 = (p3 + p2) * 0.5;
118     P s2 = s1 + ((p3 - p2).rot90());
119     return isLL(q1,q2,s1,s2);
120 }*/
121 bool cmp_x(const P &p, const P &q) {
122     if (p.x != q.x) return p.x < q.x;
123     return p.y < q.y;
124 }
125 
126 vector<P> qs;
127 
128 void convex_hull(P *ps, int n) {
129     sort(ps, ps + n, cmp_x);
130     int k = 0;
131     qs.resize(2 * n);
132     for (int i = 0; i < n; qs[k++] = ps[i++]) {
133         while (k > 1 && (qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]) < EPS)k--;
134     }
135     for (int i = n - 2, t = k; i >= 0; qs[k++] = ps[i--]) {
136         while (k > t && (qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]) < EPS)k--;
137     }
138     qs.resize(k - 1);
139 }
140 
141 //求凸包的直径
142 double convexDiameter() {
143     int qsz = qs.size();
144     if (qsz == 1)return 0;
145     if (qsz == 2) {
146         return (qs[0] - qs[1]).abs();
147     }
148     int i = 0, j = 0;
149     rep(k, qsz) {
150         if (!cmp_x(qs[i], qs[k]))i = k;
151         if (cmp_x(qs[j], qs[k])) j = k;
152     }
153     double res = 0;
154     int si = i, sj = j;
155     while (i != sj || j != si) {
156         res = max(res, (qs[i] - qs[j]).abs());
157         if ((qs[(i + 1) % qsz] - qs[i]).det(qs[(j + 1) % qsz] - qs[j]) < 0) i = (i + 1) % qsz;
158         else j = (j + 1) % qsz;
159     }
160     return res;
161 }
162 
163 
164 #endif //JHELPER_EXAMPLE_PROJECT_P_HPP
165 
166 const int MAXN = 50010;
167 P p[MAXN];
168 
169 class poj2187_Rotating_calipers {
170 public:
171     void solve() {
172         int n;
173         scanf("%d",&n);//in >> n;
174         rep(i, n) {
175             scanf("%lf%lf",&p[i].x,&p[i].y);//in >> p[i].x >> p[i].y;
176         }
177         convex_hull(p, n);
178         double ans = convexDiameter();
179         printf("%.0f\n",ans*ans);//out << ans * ans << endl;
180     }
181 };
182 
183 int main() {
184     //std::ios::sync_with_stdio(false);
185     //std::cin.tie(0);
186     poj2187_Rotating_calipers solver;
187     //std::istream &in(std::cin);
188     //std::ostream &out(std::cout);
189     solver.solve();
190     return 0;
191 }
代码君

Java:

  1 import java.io.OutputStream;
  2 import java.io.IOException;
  3 import java.io.InputStream;
  4 import java.io.PrintWriter;
  5 import java.util.Arrays;
  6 import java.io.IOException;
  7 import java.io.InputStreamReader;
  8 import java.util.StringTokenizer;
  9 import java.io.BufferedReader;
 10 import java.io.InputStream;
 11 
 12 /**
 13  * Built using CHelper plug-in
 14  * Actual solution is at the top
 15  *
 16  * @author xyiyy @https://github.com/xyiyy  @http://www.cnblogs.com/fraud/
 17  */
 18 public class Main {
 19     public static void main(String[] args) {
 20         InputStream inputStream = System.in;
 21         OutputStream outputStream = System.out;
 22         Scanner in = new Scanner(inputStream);
 23         PrintWriter out = new PrintWriter(outputStream);
 24         TaskC solver = new TaskC();
 25         solver.solve(1, in, out);
 26         out.close();
 27     }
 28 
 29     static class TaskC {
 30         Scanner in;
 31         PrintWriter out;
 32 
 33         public void solve(int testNumber, Scanner in, PrintWriter out) {
 34             this.in = in;
 35             this.out = out;
 36             run();
 37         }
 38 
 39         void run() {
 40             int n;
 41             n = in.nextInt();
 42             P[] p = new P[n];
 43             for (int i = 0; i < n; i++) p[i] = new P(in.nextInt(), in.nextInt());
 44             double ans = P.convexDiameter(P.convexHull(p));
 45             out.printf("%.0f%n", ans * ans);
 46         }
 47 
 48     }
 49 
 50     static class P implements Comparable<P> {
 51         public static final double EPS = 1e-9;
 52         public final double x;
 53         public final double y;
 54 
 55         public static double add(double a, double b) {
 56             if (Math.abs(a + b) < EPS * (Math.abs(a) + Math.abs(b))) return 0;
 57             return a + b;
 58         }
 59 
 60         public P(double x, double y) {
 61             this.x = x;
 62             this.y = y;
 63         }
 64 
 65         public P sub(P p) {
 66             return new P(add(x, -p.x), add(y, -p.y));
 67         }
 68 
 69         public double det(P p) {
 70             return add(x * p.y, -y * p.x);
 71         }
 72 
 73         public double dot(P p) {
 74             return add(x * p.x, y * p.y);
 75         }
 76 
 77         public double abs() {
 78             return Math.sqrt(abs2());
 79         }
 80 
 81         public double abs2() {
 82             return dot(this);
 83         }
 84 
 85 
 86         public String toString() {
 87             return "(" + x + ", " + y + ")";
 88         }
 89 
 90 
 91         public boolean equals(Object obj) {
 92             if (this == obj)
 93                 return true;
 94             if (obj == null)
 95                 return false;
 96             if (getClass() != obj.getClass())
 97                 return false;
 98             return compareTo((P) obj) == 0;
 99         }
100 
101 
102         public int compareTo(P p) {
103             int b = sig(x - p.x);
104             if (b != 0) return b;
105             return sig(y - p.y);
106         }
107 
108         public static int sig(double x) {
109             if (Math.abs(x) < EPS) return 0;
110             return x < 0 ? -1 : 1;
111         }
112 
113         public static P[] convexHull(P[] ps) {
114             int n = ps.length, k = 0;
115             if (n <= 1) return ps;
116             Arrays.sort(ps);
117             P[] qs = new P[n * 2];
118             for (int i = 0; i < n; qs[k++] = ps[i++]) {
119                 while (k > 1 && qs[k - 1].sub(qs[k - 2]).det(ps[i].sub(qs[k - 1])) < EPS) k--;
120             }
121             for (int i = n - 2, t = k; i >= 0; qs[k++] = ps[i--]) {
122                 while (k > t && qs[k - 1].sub(qs[k - 2]).det(ps[i].sub(qs[k - 1])) < EPS) k--;
123             }
124             P[] res = new P[k - 1];
125             System.arraycopy(qs, 0, res, 0, k - 1);
126             return res;
127         }
128 
129         public static double convexDiameter(P[] ps) {
130             int n = ps.length;
131             int is = 0, js = 0;
132             for (int i = 1; i < n; i++) {
133                 if (ps[i].x > ps[is].x) is = i;
134                 if (ps[i].x < ps[js].x) js = i;
135             }
136             double maxD = ps[is].sub(ps[js]).abs();
137             int i = is, j = js;
138             do {
139                 if (ps[(i + 1) % n].sub(ps[i]).det(ps[(j + 1) % n].sub(ps[j])) >= 0) {
140                     j = (j + 1) % n;
141                 } else {
142                     i = (i + 1) % n;
143                 }
144                 maxD = Math.max(maxD, ps[i].sub(ps[j]).abs());
145             } while (i != is || j != js);
146             return maxD;
147         }
148 
149     }
150 
151     static class Scanner {
152         BufferedReader br;
153         StringTokenizer st;
154 
155         public Scanner(InputStream in) {
156             br = new BufferedReader(new InputStreamReader(in));
157             eat("");
158         }
159 
160         private void eat(String s) {
161             st = new StringTokenizer(s);
162         }
163 
164         public String nextLine() {
165             try {
166                 return br.readLine();
167             } catch (IOException e) {
168                 return null;
169             }
170         }
171 
172         public boolean hasNext() {
173             while (!st.hasMoreTokens()) {
174                 String s = nextLine();
175                 if (s == null)
176                     return false;
177                 eat(s);
178             }
179             return true;
180         }
181 
182         public String next() {
183             hasNext();
184             return st.nextToken();
185         }
186 
187         public int nextInt() {
188             return Integer.parseInt(next());
189         }
190 
191     }
192 }
代码君

 

posted on 2015-08-30 23:55  xyiyy  阅读(305)  评论(0编辑  收藏  举报

导航