POJ 2187 Beauty Contest(凸包直径)
2015-03-02 22:48
295 查看
初级旋转卡壳get!
题意:给出一个点集,求点集中最远的两个点的距离的平方。
首先求一遍凸包(可以仅保留转折点),然后通过旋转卡壳(复杂度:o(nlogn))得到直径。
对于凸包的某一个点,凸包上总会有一个点距离它最远,并且是该点的对踵点。
对踵点:
如果过凸包上的两个点可以画一对平行直线,
使凸包上的所有点都夹在两条平行线之间或落在平行线上,
那么这两个点叫做一对对踵点。
最远距离点对一定是一对对踵点。
想象这两条平行线,渐渐旋转,最终和凸包上的一条边重合,如上图。
而对踵点与这条边构成的三角形,也一定是所有点和这条边构成的三角形中面积最大的。
按某一个固定的方向选择点,三角形的面积呈现先增后减的趋势。并且,按同一个方向选取下一条边时,下一个点的最远对踵点的次序,一定不会在前一个点的对踵点的前面(注意凸包的点是环状的,所以我怎么说都对...)。
对于算点与点之间的最远距离,显然是可以通过这个办法来计算的。
取最大值的时候,要考虑到一条边上有两个点。比如在图中,B的最远点是E,计算面积时,边BC上的最大三角形是BCE,但BE和CE两边都比较一次。
题意:给出一个点集,求点集中最远的两个点的距离的平方。
首先求一遍凸包(可以仅保留转折点),然后通过旋转卡壳(复杂度:o(nlogn))得到直径。
对于凸包的某一个点,凸包上总会有一个点距离它最远,并且是该点的对踵点。
对踵点:
如果过凸包上的两个点可以画一对平行直线,
使凸包上的所有点都夹在两条平行线之间或落在平行线上,
那么这两个点叫做一对对踵点。
最远距离点对一定是一对对踵点。
想象这两条平行线,渐渐旋转,最终和凸包上的一条边重合,如上图。
而对踵点与这条边构成的三角形,也一定是所有点和这条边构成的三角形中面积最大的。
按某一个固定的方向选择点,三角形的面积呈现先增后减的趋势。并且,按同一个方向选取下一条边时,下一个点的最远对踵点的次序,一定不会在前一个点的对踵点的前面(注意凸包的点是环状的,所以我怎么说都对...)。
对于算点与点之间的最远距离,显然是可以通过这个办法来计算的。
取最大值的时候,要考虑到一条边上有两个点。比如在图中,B的最远点是E,计算面积时,边BC上的最大三角形是BCE,但BE和CE两边都比较一次。
#include <algorithm> #include <iostream> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <math.h> using namespace std; #define eps 1e-10 #define MAXN 50010 #define max(x, y) (x > y ? x : y) #define min(x, y) (x < y ? x : y) #define sig(x) ((x > eps) - (x < -eps)) #define cross(o, a, b) ((p[a] - p[o]) ^ (p[b] - p[o])) const double pi = acos(-1.0); typedef struct Point { int x, y; Point() {} Point(int _x, int _y): x(_x), y(_y) {} bool operator <(const Point &argu) const { return sig(x - argu.x) == 0 ? y < argu.y : x < argu.x; } // double dis(const Point &argu) const // { // return sqrt((x - argu.x) * (x - argu.x) + (y - argu.y) * (y - argu.y)); // } int dis2(const Point &argu) const { return (x - argu.x) * (x - argu.x) + (y - argu.y) * (y - argu.y); } int operator ^(const Point &argu) const { return x * argu.y - y * argu.x; } // double operator *(const Point &argu) const // { // return x * argu.x + y * argu.y; // } Point operator -(const Point &argu) const { return Point(x - argu.x, y - argu.y); } // double len2() const // { // return x * x + y * y; // } // double len() const // { // return sqrt(x * x + y * y); // } void in() { scanf("%d%d", &x, &y); } void out() { printf("%d %d\n", x, y); } }Vector; inline double Cross(Point p[], int o, int a, int b) { return (p[a] - p[o]) ^ (p[b] - p[o]); } int ConvexHull(Point p[], int n, int q[]) { sort(p, p + n); int top = 0; for(int i = 0; i < n; i++) { while(top > 1 && Cross(p, q[top - 2], q[top - 1], i) <= 0) top--; q[top++] = i; } int t = top; for(int i = n - 2; i >= 0; i--) { while(top > t && Cross(p, q[top - 2], q[top - 1], i) <= 0) top--; q[top++] = i; } top--; return top; } int RotatingCalipers(Point p[], int n, int q[]) { int ans = 0, c = 1; q = q[0]; for(int i = 0; i < n; i++) { while(Cross(p, q[c + 1], q[i], q[i + 1]) > Cross(p, q[c], q[i], q[i + 1])) c = (c + 1) % n; ans = max(ans, max(p[q[i]].dis2(p[q[c]]), p[q[i + 1]].dis2(p[q[c]]))); } return ans; } Point pp[MAXN], c; int n, hn, q[MAXN]; int solve() { hn = ConvexHull(pp, n, q); //for(int i = 0; i < hn; i++) pp[q[i]].out(); return RotatingCalipers(pp, hn, q); } int main() { // freopen("2187.in", "r", stdin); while(~scanf("%d", &n)) { for(int i = 0; i < n; i++) pp[i].in(); printf("%d\n", solve()); } return 0; }
相关文章推荐
- POJ 2187 Beauty Contest【旋转卡壳求凸包直径】
- 【凸包直径&平面最远点对&对锺点(旋转卡壳)】poj 2187 Beauty Contest
- POJ 2187 Beauty Contest【旋转卡壳求凸包直径】
- poj 2187 Beauty Contest , 旋转卡壳求凸包的直径的平方
- poj2187 Beauty Contest 凸包求点集的直径
- poj 2187 Beauty Contest , 旋转卡壳求凸包的直径的平方
- 【POJ 2187】Beauty Contest(凸包直径、旋转卡壳)
- POJ 2187 Beauty Contest(凸包+旋转卡壳)
- Poj 2187 Beauty Contest_旋转凸包卡壳
- poj-2187-凸包-旋转卡壳法求直径
- poj_2187求凸包直径
- poj 2187 Beauty Contest(凸包)
- POJ 2187 Beauty Contest 凸包+旋转卡壳
- POJ 2187 Beauty Contest (凸包)
- poj_2187求凸包直径
- POJ 2187 Beauty Contest (凸包)
- 【POJ 2187】Beauty Contest 凸包+旋转卡壳
- poj 2187 Beauty Contest(凸包求解多节点的之间的最大距离)
- POJ2187-Beauty Contest-凸包
- poj2187-Beauty Contest 求凸包最远距离(旋转卡壳算法模板题)