POJ 2187 计算几何之旋转卡壳

来源:互联网 发布:red flag linux 8.0 编辑:程序博客网 时间:2024/06/10 18:01

首先这个题目可以用先求凸包再暴力枚举的方法通过,原因不是数据出水了,而是因为有一个奇葩的结论就是坐标值不超过K的不同的多边形最多不会超过 sqrt (K) 个 所以求出凸包后暴力枚举时间复杂度是可以接受的

  1. 关于多边形的切线 : 就是说一条直线与多边形相交,并且多边形在直线的一侧,这样的直线称之为多边形的切线,
  2. 关于多边形的对踵点 : 多边形的对踵点就是 : 两条平行的多边形切线上的与多边形相交的点。 对踵点有三种情况

    1. 两条切线都只与多边形有一个交点
    2. 两条切线都与多边形有无数多个交点
    3. 一个有一个交点,另一个有无穷多个交点
  3. 关于旋转卡壳 : 是一种求平面上所有点的最远对点的算法,我们知道可以通过求凸包 + 枚举凸包上的点的方式求出平面上所有点的最远距离,但是这种方法在凸包上的点过多的时候时间复杂度退化到 O (n ^ 2) 对于有些题目是不可以接受的,这个时候就要采取旋转卡壳的方法求平面上任意两个点的最远距离。(也叫做多边形的直径) 因为可以保证对踵点的个数不会超过 3/2n 个 所以算法的时间复杂度可以保证

  4. 具体实现
#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <cmath>using namespace std;const int maxn = 50005;const double eps = 1e-8;const int INF = 1e9 + 7;struct point {    int x,y;}p[maxn];point poly[maxn] = {0};point init;int n;int tot;int ab (int x) {return x > 0 ? x : -x;}int dist (point a,point b) {    return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);}int cross (int x1,int y1,int x2,int y2) {    return x1 * y2 - x2 * y1;}bool cmp (const point a,const point b) {    if (cross(a.x - init.x,a.y - init.y,b.x - init.x,b.y - init.y) != 0) {        return cross(a.x - init.x,a.y - init.y,b.x - init.x,b.y - init.y) > 0;    }    else {        return dist (a,init) < dist (b,init);    }}void tubao () {    for (int i = 1;i <= 2; ++ i) poly[i] = p[i];    tot = 2;    for (int i = 3;i <= n; ++ i) {        while (tot >= 2) {            point p1,p2,p3;            p1 = poly[tot];            p2 = poly[tot - 1];            p3 = p[i];            if (cross (p1.x - p2.x,p1.y - p2.y,p3.x - p1.x,p3.y - p1.y) <= 0) tot --;            else break;        }        poly[++ tot] = p[i];    }}int rotating () {    if (tot == 2) return dist (poly[1],poly[2]);    poly[++tot] = poly[1];    int ans = 0;    int u = 2;    for (int i = 1;i < tot; ++ i) {        int mxd = max (dist (poly[u],poly[i]),dist (p[u],poly[i + 1]));        ans = max (ans,mxd);        while (ab (cross(poly[i].x - poly[u].x, poly[i].y - poly[u].y, poly[i + 1].x - poly[u].x, poly[i + 1].y - poly[u].y)) <= ab (cross(poly[i].x - poly[u + 1].x, poly[i].y - poly[u + 1].y, poly[i + 1].x - poly[u + 1].x, poly[i + 1].y - poly[u + 1].y))) {                u = u % tot + 1;                mxd = max (dist (poly[u],poly[i]),dist (p[u],poly[i + 1]));                ans = max (ans,mxd);        }    }    return ans;}int main () {    ios_base :: sync_with_stdio(false);    while (cin >> n) {        for (int i = 1;i <= n; ++ i) {            cin >> p[i].x >> p[i].y;            if (p[i].y < p[1].y) {                swap (p[1],p[i]);            }            else if (p[i].y == p[1].y && p[i].x < p[1].x) {                swap (p[1],p[i]);            }        }        if (n == 2) {            cout << dist (p[1],p[2]) << endl;            continue;        }        init = p[1];        sort (p + 1,p + n + 1,cmp);        tubao();        cout << rotating() << endl;    }    return 0;}
原创粉丝点击