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.
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
* 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 }