poj2187 Beauty Contest(旋转卡壳)
转载请注明出处: 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());
} }
}
代码君
poj2187 Beauty Contest(旋转卡壳)的更多相关文章
- poj 2187:Beauty Contest(旋转卡壳)
Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 32708 Accepted: 10156 Description Bes ...
- poj 2187 Beauty Contest , 旋转卡壳求凸包的直径的平方
旋转卡壳求凸包的直径的平方 板子题 #include<cstdio> #include<vector> #include<cmath> #include<al ...
- poj 2187 Beauty Contest——旋转卡壳
题目:http://poj.org/problem?id=2187 学习材料:https://blog.csdn.net/wang_heng199/article/details/74477738 h ...
- P1452 Beauty Contest 旋转卡壳
\(\color{#0066ff}{题目描述}\) 贝茜在牛的选美比赛中赢得了冠军"牛世界小姐".因此,贝西会参观N(2 < = N < = 50000)个农场来传播善 ...
- poj 2187 Beauty Contest —— 旋转卡壳
题目:http://poj.org/problem?id=2187 学习资料:https://blog.csdn.net/wang_heng199/article/details/74477738 h ...
- POJ-2187 Beauty Contest,旋转卡壳求解平面最远点对!
凸包(旋转卡壳) 大概理解了凸包A了两道模板题之后在去吃饭的路上想了想什么叫旋转卡壳呢?回来无聊就搜了一下,结果发现其范围真广. 凸包: 凸包就是给定平面图上的一些点集(二维图包),然后求点集组成的 ...
- poj2187 Beauty Contest (凸包 + 旋转卡壳)
Beauty Contest Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 38349 Accepted: 11851 ...
- POJ2187 Beauty Contest (旋转卡壳算法 求直径)
POJ2187 旋转卡壳算法如图 证明:对于直径AB 必然有某一时刻 A和B同时被卡住 所以旋转卡壳卡住的点集中必然存在直径 而卡壳过程显然是O(n)的 故可在O(n)时间内求出直径 凸包具有良好的性 ...
- [USACO2003][poj2187]Beauty Contest(凸包+旋转卡壳)
http://poj.org/problem?id=2187 题意:老题了,求平面内最远点对(让本渣默默想到了悲剧的AHOI2012……) 分析: nlogn的凸包+旋转卡壳 附:http://www ...
随机推荐
- CentOS下安装nginx并且升级nginx到最新版
yum install yum-fastestmirro yum install nginxyum update nginx(之前先配置一下)vim /etc/yum.repos.d/nginx.re ...
- QQ原创表情添加
有时候与QQ好友聊天时会收到一些自己比较喜欢的原创表情,如果我们想把这些QQ不支持直接保存的原创表情保存到电脑上该怎么做呢?我们以原创表情图片为例简单介绍一下. 首先,先建立一个存放表情图片的文件夹. ...
- php设计模式2策略模式
<?php /** ****************************************************** * 策略模式:策略模式针对一组算法,将每一个算法封装到具有共同接 ...
- Serializable序列化
对象的输入输出流 package file; import java.io.File; import java.io.FileInputStream; import java.io.FileOutpu ...
- .NET MVC插件化开发(支持Script和css压缩)
上一篇博文里面,没有支持Script和css的压缩功能以及script和css的路径问题也没有解决,所以重新发布一个版本,解决了这几个问题,并且优化了插件路由注册,现在可以很方便的实现热插拔web插件 ...
- SVM及其对偶
引自 http://my.oschina.net/wangguolongnk/blog/111349 1. 支持向量机的目的是什么? 对于用于分类的支持向量机来说,给定一个包含正例和反例(正样本点和负 ...
- CentOS安装Nginx,并配置nodejs反向代理
安装介绍 安装位置:/usr/local/nginx nginx安装包下载地址:http://nginx.org/download/nginx-1.7.11.tar.gz 安装依赖软件 安装nginx ...
- Android开发 解决AlertDialog中的EditText无法调出输入法的问题
在AlertDialog中使用自定义的View,如果View中有EditText,在上面点击,默认是跳不出软键盘的,不是焦点的问题.解决方法,有两种,一是把AlertDialog换成Dialog,但这 ...
- 好吧,使用sql实现Dijkstra算法
我本来不想做这么蛋疼的事情的,可是更蛋疼的是我看了王大神的博客然后中毒了!我发誓再!不!看!了!不过问题本身还是有一点意思的,正好学过图论没有实现过dijkstra,刚好在慕课上又学了一点pl/sql ...
- coreOS+Docker新一代企业轻量级Linux
CoreOS官网主页使用一句话概括其理 念:“A new way to think about servers”,以及紧接着的“CoreOS is Linux for massive server d ...