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 ...
随机推荐
- thinkphp基础入门(1)
ThinkPHP目录如下,Application顾名思义就是应用的意思(我们的代码放在这里),Public就是公共文件的意思(主要放JS CSS 等前端资源文件),ThinkPHP文件是框架的核心包( ...
- 转:分享13款PHP开发框架
文章来自于:http://mashable.com/2014/04/04/php-frameworks-build-applications/ Building software applicatio ...
- http协议的各个版本及区别
这个东西在一篇博文上面看见的,谢谢原博主提供!又学习了...
- 自动删除n天前日志
自动删除n天前日志 linux 是一个很能自动产生文件的系统,日志.邮件.备份等.虽然现在硬盘廉价,我们可以有很多硬盘空间供这些文件浪费,让系统定时清理一些不需要的文件很有一种 爽快的事情.不用你去每 ...
- HDU5196--DZY Loves Inversions 树状数组 逆序数
题意查询给定[L, R]区间内 逆序对数 ==k的子区间的个数. 我们只需要求出 子区间小于等于k的个数和小于等于k-1的个数,然后相减就得出答案了. 对于i(1≤i≤n),我们计算ri表示[i,ri ...
- SQL-Customers Who Never Order
Suppose that a website contains two tables, the Customers table and the Orders table. Write a SQL qu ...
- linux内存管理--slab及其代码解析
Linux内核使用了源自于 Solaris 的一种方法,但是这种方法在嵌入式系统中已经使用了很长时间了,它是将内存作为对象按照大小进行分配,被称为slab高速缓存. 内存管理的目标是提供一种方法,为实 ...
- linux中cat、more、less、tail、head命令
cat命令功能用于显示整个文件的内容单独使用没有翻页功能因此经常和more命令搭配使用,cat命令还有就是将数个文件合并成一个文件的功能. more命令功能:让画面在显示满一页时暂停,此时可按空格健继 ...
- Spring MVC 前后台数据交互
本文是转载文章,感觉比较好,如有侵权,请联系本人,我将及时删除. 原文网址地址:<Spring MVC 前后台数据交互> 1.服务端数据到客户端 (1)返回页面,Controller中方法 ...
- StoryBoard 设置TabBar SelectImage 和tintColor
如图:StoryBoard 结构是 Tabbar + Navi + ViewController 需求:需要修改TabBar的Image 和SelectImage 设置Image 设置SelectIm ...