POJ-2178 Beauty Contest 凸包+旋转卡壳求最远点对

来源:互联网 发布:选择题自动填充软件 编辑:程序博客网 时间:2024/05/16 05:52

大家都很强, 可与之共勉。

题意:
  给您n(n50000)个平面上的点,以坐标的形式给出。让您求出其中两点之间最远距离的平方。

  eps设丑了T了一夜夜夜夜夜夜

题解:

我们首先一定可以秒看出,最远点对一定在凸包上(反证法)。
然后就旋转卡壳。
由这个图
这里写图片描述
我们可以发现,对于一条边来说,其余另外的点围成的面积,一定是单峰增长的。而使之面积最大的那个点,就是对于他们来讲的最远点,算一下距离,下一次游客已在这一次的基础上移动,保证了时间复杂度。

代码(表示暴力也跑得飞快):

# include <cmath># include <cstdio># include <algorithm>const double eps = 1e-8 ;inline int dcmp ( double x )  {    return ( x > -eps ) - ( x < eps ) ;}typedef struct Vector  {    double x, y ;    Vector ( ) {     }    Vector ( double x, double y ) : x ( x ), y ( y )  {  }    inline Vector operator + ( const Vector rhs )  const  {        return Vector ( x + rhs.x, y + rhs.y ) ;    }    inline Vector operator - ( const Vector rhs ) const  {        return Vector ( x - rhs.x, y - rhs.y ) ;    }    inline Vector operator * ( const double k ) const  {        return Vector ( x * k, y * k ) ;    }    inline Vector operator / ( const double k ) const  {        return Vector ( x / k, y / k ) ;    }    inline double operator * ( const Vector rhs ) const  {        return x * rhs.x + y * rhs.y ;    }    inline double operator % ( const Vector rhs ) const  {        return x * rhs.y - y * rhs.x ;    }} Vector, Point ;//得到sp-op和ep-op的叉积//>0时ep在opsp的逆时针方向,<0时顺时针,=0时共线inline double Cross ( Point& sp, Point& ep, Point& op )  {    return ( sp.x - op.x ) * ( ep.y - op.y ) - ( ep.x - op.x ) * ( sp.y - op.y ) ;}struct Cmp  {    inline bool operator ( ) ( const Point& a, const Point& b )  {        return ( a.x == b.x ) ? a.y < b.y : a.x < b.x ;    }} ;/*------Graham求凸包----*///n为原图的点数,p []为原图的点(0~n-1),top为凸包点的数量(0~top-1),res[]为凸包点的下标,。inline int Graham ( Point* p, int n, Point* res )  {    int len ;    register int top = 1 ;    std :: sort ( p, p + n, Cmp ( ) ) ;    for ( int i = 0 ; i < 3 ; ++ i ) res [i] = p [i] ;    for ( int i = 2 ; i < n ; ++ i )  {        while ( top && dcmp ( Cross ( p [i], res [top], res [top - 1] ) ) >= 0 ) -- top ;        res [++ top] = p [i] ;    }    len = top ;    res [++ top] = p [n - 2] ;    for ( int i = n - 3 ; i >= 0 ; -- i )  {        while ( top != len && dcmp ( Cross ( p[i], res [top], res [top - 1] ) ) >= 0 ) -- top ;        res [++ top] = p [i] ;    }    return top ;}Point p [50050], con [50050] ;inline int dis ( Point a, Point b )  {    return ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ) ;}int main ( )  {//  freopen ( "in.txt", "r", stdin ) ;    int n ;    scanf ( "%d", & n ) ;    for ( int i = 0 ; i < n ; ++ i )  {        int a, b ;        scanf ( "%d%d", & a, & b ) ;        p [i] = Point ( ( double ) a, ( double ) b ) ;    }    int cnt = Graham ( p, n, con ) ;    int rt ( 0 ) ;    con [cnt] = con [0] ;    for ( int p = 0, q = 1 ; p < cnt ; ++ p )  {        while ( dcmp ( fabs ( Cross ( con [q + 1], con [p], con [p + 1] ) ) - fabs ( Cross ( con [q], con [p], con [p + 1] ) ) ) > 0 )  if ( ++ q >= cnt )  q -= cnt ; // !!!        rt = std :: max ( rt, std :: max ( dis ( con [q], con [p] ), dis ( con [q], con [p + 1] ) ) ) ;        rt = std :: max ( rt, std :: max ( dis ( con [q + 1], con [p] ), dis ( con [q + 1], con [p + 1] ) ) ) ;    }/*  for ( int i = 0 ; i < cnt ; ++ i )        for ( int j = i + 1 ; j < cnt ; ++ j )  {            rt = std :: max ( rt, int ( ( con [i].x - con [j].x ) * ( con [i].x - con [j].x ) + ( con [i].y - con [j].y ) * ( con [i].y - con [j].y ) ) ) ;        }*/    printf ( "%d\n", rt ) ;}
阅读全文
0 0
原创粉丝点击