poj2187

题意:求凸包直径。

分析:用graham按纵坐标序,再用旋转卡壳法。

但是模板我并没有完全理解,为什么要用点到直线的距离呢

View Code
#include < iostream >
#include
< cstdlib >
#include
< cstring >
#include
< cstdio >
#include
< algorithm >
using namespace std;

#define maxn 50005

struct Xpoint
{
int x, y;
} pnt[maxn], res[maxn];

int n;

bool mult(Xpoint sp, Xpoint ep, Xpoint op)
{
return (sp.x - op.x) * (ep. y - op.y) >= (ep.x - op.x) * (sp.y - op.y);
}

bool operator < ( const Xpoint & l, const Xpoint & r)
{
return l.y < r. y || (l.y == r.y && l.x < r.x);
}

int cross(Xpoint a, Xpoint b, Xpoint o)
{
return (a.x - o.x) * (b.y - o.y) - (b.x - o.x) * (a.y - o.y);
}

int graham()
{
int i, len, top = 1 ;
sort(pnt, pnt
+ n);
if (n == 0 )
return 0 ;
res[
0 ] = pnt[ 0 ];
if (n == 1 )
return 1 ;
res[
1 ] = pnt[ 1 ];
if (n == 2 )
return 2 ;
res[
2 ] = pnt[ 2 ];
for (i = 2 ; i < n; i ++ )
{
while (top && mult(pnt[i], res[top], res[top - 1 ]))
top
-- ;
res[
++ top] = pnt[i];
}
len
= top;
res[
++ top] = pnt[n - 2 ];
for (i = n - 3 ; i >= 0 ; i -- )
{
while (top != len && mult(pnt[i], res[top], res[top - 1 ]))
top
-- ;
res[
++ top] = pnt[i];
}
return top;
}

int dist2(Xpoint a, Xpoint b)
{
return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}

int rotating_calipers(Xpoint * ch, int n)
{
int q = 1 , ans = 0 ;
ch[n]
= ch[ 0 ];
for ( int p = 0 ; p < n; p ++ )
{
while (cross(ch[p + 1 ], ch[q + 1 ], ch[p]) > cross(ch[p + 1 ], ch[q], ch[p]))
q
= (q + 1 ) % n;
ans
= max(ans, max(dist2(ch[p], ch[q]), dist2(ch[p + 1 ], ch[q + 1 ])));
}
return ans;
}

int main()
{
// freopen("t.txt", "r", stdin);
scanf( " %d " , & n);
for ( int i = 0 ; i < n; i ++ )
scanf(
" %d%d " , & pnt[i].x, & pnt[i].y);
int count = graham();
int ans = rotating_calipers(res, count);
printf(
" %d\n " , ans);
return 0 ;
}

你可能感兴趣的:(poj)