转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 31214 | Accepted: 9681 |
Description
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
* Lines 2..N+1: Two space-separated integers x and y specifying coordinate of each farm
Output
Sample Input
4
0 0
0 1
1 1
1 0
Sample Output
2
Hint
求平面的最远点对。
由于点的范围在-10000到10000之间,所以取完凸包后,凸包上的点的数目并不会很多,不会超过根号M个,所以可以求完凸包之后直接暴力枚举凸包上的点来做。
/**
* code generated by JHelper
* More info: https://github.com/AlexeyDmitriev/JHelper
* @author xyiyy @https://github.com/xyiyy
*/ #include <iostream>
#include <fstream> //#####################
//Author:fraud
//Blog: http://www.cnblogs.com/fraud/
//#####################
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <sstream>
#include <ios>
#include <iomanip>
#include <functional>
#include <algorithm>
#include <vector>
#include <string>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <climits>
#include <cctype> using namespace std;
#define rep(X, N) for(int X=0;X<N;X++) const double EPS = 1e-; double add(double a, double b) {
if (abs(a + b) < EPS * (abs(a) + abs(b)))return ;
return a + b;
} struct P {
double x, y; P() { } P(double x, double y) : x(x), y(y) { } P operator+(P p) {
return P(add(x, p.x), add(y, p.y));
} P operator-(P p) {
return P(add(x, -p.x), add(y, -p.y));
} double dot(P p) {
return add(x * p.x, y * p.y);
} double det(P p) {
return add(x * p.y, -y * p.x);
}
}; double dist(P p, P q) {
return (p - q).dot(p - q);
} bool cmp_x(const P &p, const P &q) {
if (p.x != q.x)return p.x < q.x;
return p.y < q.y;
} vector<P> convex_hull(P *ps, int n) {
sort(ps, ps + n, cmp_x);
int k = ;
vector<P> qs(n * );
for (int i = ; i < n; qs[k++] = ps[i++]) {
while (k > && (qs[k - ] - qs[k - ]).det(ps[i] - qs[k - ]) < EPS)k--;
}
for (int i = n - , t = k; i >= ; qs[k++] = ps[i--]) {
while (k > t && (qs[k - ] - qs[k - ]).det(ps[i] - qs[k - ]) < EPS)k--;
}
qs.resize(k - );
return qs;
} const int MAXN = ; class poj2187 {
public:
void solve() {
int n;
scanf("%d",&n);//in >> n;
P *ps = new P[MAXN];
rep(i, n) {
scanf("%lf%lf",&ps[i].x,&ps[i].y);//in >> ps[i].x >> ps[i].y;
}
vector<P> qs = convex_hull(ps, n);
double res = ;
rep(i, qs.size()) {
rep(j, i) {
res = max(res, dist(qs[i], qs[j]));
}
}
printf("%.0f\n",res);
//out << fixed << setprecision(0) << res << endl;
}
}; int main() {
//std::ios::sync_with_stdio(false);
//std::cin.tie(0);
poj2187 solver;
//std::istream &in(std::cin);
// std::ostream &out(std::cout);
solver.solve();
return ;
}
代码君
对于凸包上最远的两个点,其实可以使用旋转卡壳来做,其实旋转卡壳的思想是比较容易理解的,首先找到对踵点对,
不明白的可以先看一下以下链接
https://en.wikipedia.org/wiki/Rotating_calipers
然后在考虑转移的情况,在凸包上,对于一个点和其他所有点的距离,绕一圈,正好构成一个单峰函数,那么,对踵点对就一定是在变小的那个地方,所以这样想通后只要找出所有的对踵点对间距离的最大值,这样原来需要在凸包上枚举所有点的O(n^2)的方法就可以通过旋转卡壳改进成O(n)了,外加上前面求凸包O(nlogn)的复杂度,这道题就可以轻松切掉了。
下面附上C++版和Java版的代码
C++:
/**
* code generated by JHelper
* More info: https://github.com/AlexeyDmitriev/JHelper
* @author xyiyy @https://github.com/xyiyy
*/ #include <iostream>
#include <fstream> //#####################
//Author:fraud
//Blog: http://www.cnblogs.com/fraud/
//#####################
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <sstream>
#include <ios>
#include <iomanip>
#include <functional>
#include <algorithm>
#include <vector>
#include <string>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <climits>
#include <cctype> using namespace std;
#define rep(X, N) for(int X=0;X<N;X++) //
// Created by xyiyy on 2015/8/10.
// #ifndef JHELPER_EXAMPLE_PROJECT_P_HPP
#define JHELPER_EXAMPLE_PROJECT_P_HPP const double EPS = 1e-; double add(double a, double b) {
if (fabs(a + b) < EPS * (fabs(a) + fabs(b)))return ;
return a + b;
} class P {
public:
double x, y;
P() {}
P(double x, double y):x(x),y(y){} P operator+(const P &p) {
return P(add(x, p.x), add(y, p.y));
} P operator-(const P &p) {
return P(add(x, -p.x), add(y, -p.y));
} P operator*(const double &d) {
return P(x * d, y * d);
} P operator/(const double &d) {
return P(x / d, y / d);
} double dot(P p) {
return add(x * p.x, y * p.y);
} double det(P p) {
return add(x * p.y, -y * p.x);
} double abs() {
return sqrt(abs2());
} double abs2() {
return dot(*this);
} }; //直线和直线的交点
/*P isLL(P p1,P p2,P q1,P q2){
double d = (q2 - q1).det(p2 - p1);
if(sig(d)==0)return NULL;
return intersection(p1,p2,q1,q2);
}*/ //四点共圆判定
/*bool onC(P p1,P p2,P p3,P p4){
P c = CCenter(p1,p2,p3);
if(c == NULL) return false;
return add((c - p1).abs2(), -(c - p4).abs2()) == 0;
}*/ //三点共圆的圆心
/*P CCenter(P p1,P p2,P p3){
//if(disLP(p1, p2, p3) < EPS)return NULL;//三点共线
P q1 = (p1 + p2) * 0.5;
P q2 = q1 + ((p1 - p2).rot90());
P s1 = (p3 + p2) * 0.5;
P s2 = s1 + ((p3 - p2).rot90());
return isLL(q1,q2,s1,s2);
}*/
bool cmp_x(const P &p, const P &q) {
if (p.x != q.x) return p.x < q.x;
return p.y < q.y;
} vector<P> qs; void convex_hull(P *ps, int n) {
sort(ps, ps + n, cmp_x);
int k = ;
qs.resize( * n);
for (int i = ; i < n; qs[k++] = ps[i++]) {
while (k > && (qs[k - ] - qs[k - ]).det(ps[i] - qs[k - ]) < EPS)k--;
}
for (int i = n - , t = k; i >= ; qs[k++] = ps[i--]) {
while (k > t && (qs[k - ] - qs[k - ]).det(ps[i] - qs[k - ]) < EPS)k--;
}
qs.resize(k - );
} //求凸包的直径
double convexDiameter() {
int qsz = qs.size();
if (qsz == )return ;
if (qsz == ) {
return (qs[] - qs[]).abs();
}
int i = , j = ;
rep(k, qsz) {
if (!cmp_x(qs[i], qs[k]))i = k;
if (cmp_x(qs[j], qs[k])) j = k;
}
double res = ;
int si = i, sj = j;
while (i != sj || j != si) {
res = max(res, (qs[i] - qs[j]).abs());
if ((qs[(i + ) % qsz] - qs[i]).det(qs[(j + ) % qsz] - qs[j]) < ) i = (i + ) % qsz;
else j = (j + ) % qsz;
}
return res;
} #endif //JHELPER_EXAMPLE_PROJECT_P_HPP const int MAXN = ;
P p[MAXN]; class poj2187_Rotating_calipers {
public:
void solve() {
int n;
scanf("%d",&n);//in >> n;
rep(i, n) {
scanf("%lf%lf",&p[i].x,&p[i].y);//in >> p[i].x >> p[i].y;
}
convex_hull(p, n);
double ans = convexDiameter();
printf("%.0f\n",ans*ans);//out << ans * ans << endl;
}
}; int main() {
//std::ios::sync_with_stdio(false);
//std::cin.tie(0);
poj2187_Rotating_calipers solver;
//std::istream &in(std::cin);
//std::ostream &out(std::cout);
solver.solve();
return ;
}
代码君
Java:
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.io.InputStream; /**
* Built using CHelper plug-in
* Actual solution is at the top
*
* @author xyiyy @https://github.com/xyiyy @http://www.cnblogs.com/fraud/
*/
public class Main {
public static void main(String[] args) {
InputStream inputStream = System.in;
OutputStream outputStream = System.out;
Scanner in = new Scanner(inputStream);
PrintWriter out = new PrintWriter(outputStream);
TaskC solver = new TaskC();
solver.solve(, in, out);
out.close();
} static class TaskC {
Scanner in;
PrintWriter out; public void solve(int testNumber, Scanner in, PrintWriter out) {
this.in = in;
this.out = out;
run();
} void run() {
int n;
n = in.nextInt();
P[] p = new P[n];
for (int i = ; i < n; i++) p[i] = new P(in.nextInt(), in.nextInt());
double ans = P.convexDiameter(P.convexHull(p));
out.printf("%.0f%n", ans * ans);
} } static class P implements Comparable<P> {
public static final double EPS = 1e-;
public final double x;
public final double y; public static double add(double a, double b) {
if (Math.abs(a + b) < EPS * (Math.abs(a) + Math.abs(b))) return ;
return a + b;
} public P(double x, double y) {
this.x = x;
this.y = y;
} public P sub(P p) {
return new P(add(x, -p.x), add(y, -p.y));
} public double det(P p) {
return add(x * p.y, -y * p.x);
} public double dot(P p) {
return add(x * p.x, y * p.y);
} public double abs() {
return Math.sqrt(abs2());
} public double abs2() {
return dot(this);
} public String toString() {
return "(" + x + ", " + y + ")";
} public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
return compareTo((P) obj) == ;
} public int compareTo(P p) {
int b = sig(x - p.x);
if (b != ) return b;
return sig(y - p.y);
} public static int sig(double x) {
if (Math.abs(x) < EPS) return ;
return x < ? - : ;
} public static P[] convexHull(P[] ps) {
int n = ps.length, k = ;
if (n <= ) return ps;
Arrays.sort(ps);
P[] qs = new P[n * ];
for (int i = ; i < n; qs[k++] = ps[i++]) {
while (k > && qs[k - ].sub(qs[k - ]).det(ps[i].sub(qs[k - ])) < EPS) k--;
}
for (int i = n - , t = k; i >= ; qs[k++] = ps[i--]) {
while (k > t && qs[k - ].sub(qs[k - ]).det(ps[i].sub(qs[k - ])) < EPS) k--;
}
P[] res = new P[k - ];
System.arraycopy(qs, , res, , k - );
return res;
} public static double convexDiameter(P[] ps) {
int n = ps.length;
int is = , js = ;
for (int i = ; i < n; i++) {
if (ps[i].x > ps[is].x) is = i;
if (ps[i].x < ps[js].x) js = i;
}
double maxD = ps[is].sub(ps[js]).abs();
int i = is, j = js;
do {
if (ps[(i + ) % n].sub(ps[i]).det(ps[(j + ) % n].sub(ps[j])) >= ) {
j = (j + ) % n;
} else {
i = (i + ) % n;
}
maxD = Math.max(maxD, ps[i].sub(ps[j]).abs());
} while (i != is || j != js);
return maxD;
} } static class Scanner {
BufferedReader br;
StringTokenizer st; public Scanner(InputStream in) {
br = new BufferedReader(new InputStreamReader(in));
eat("");
} private void eat(String s) {
st = new StringTokenizer(s);
} public String nextLine() {
try {
return br.readLine();
} catch (IOException e) {
return null;
}
} public boolean hasNext() {
while (!st.hasMoreTokens()) {
String s = nextLine();
if (s == null)
return false;
eat(s);
}
return true;
} public String next() {
hasNext();
return st.nextToken();
} public int nextInt() {
return Integer.parseInt(next());
} }
}
代码君