POJ 2187--Beauty Contest

来源:互联网 发布:mysql 导入employees 编辑:程序博客网 时间:2024/05/01 04:46

题意:求一点集的最远欧式距离。

  • 点集规模较大,暴力会超时,可以证明此最远距离必定为点集的凸包直径。
Graham算法求凸包:
  1. 首先选出位于左下方的点p[0],然后根据此点到其它点的极角(向量与x轴正半轴夹角)对其它点进行排序,若极角相同,只选择距离最远的点。
  2. 利用凸多边形的判定,经过操作1后点集是按逆时针排序(极角增大)的,又由于凸多边形只朝着一个方向旋转,即设连续三点p[i],p[i+1],p[i+2],我们有向量p[i]p[i+1]差乘向量p[i]p[i+2]只可能大于零,所以要去除非左转的点。
  3. 经过以上操作可知,若排序后剩余点数m >= 3,则p[0],p[1],p[m-1]是肯定存在于凸包中的。但是实际中我们是在形成凸包的过程中才删除极角相同点的,所以仅排序后的点p[1]是不一定存在于凸包中的,所以控制convexNum下限为1。
  • 求出凸包后,可以使用枚举计算距离,也可以使用旋转卡壳算法。参考:http://www.cppblog.com/staryjy/archive/2009/11/19/101412.html。注意其中的越界取模
注意使用qsort函数时,若小返回false会排序出错,返回负数则不会,也可以直接使用sort,其cmp函数是返回bool的。


#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>using namespace std;#define square(x) ((x)*(x))#define maxN 50005struct node{    int x,y;};node farms[maxN];node convex[maxN];int convexNum;int N;int crossMult(node p0,node p1,node p2)    //p0p1 x p0p2{    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);}int calcDis(node p0,node p1){    return square(p0.x-p1.x)+square(p0.y-p1.y);}bool cmp(node p1,node p0){    int ans = crossMult(farms[0],p1,p0);            //从最低点到p0,p1两点的转向判断两向量极角大小    if(ans > 0||(ans == 0&&(calcDis(farms[0],p0) > calcDis(farms[0],p1))))      //若极角相同即三点共线,远的点更大        return true;    return false;}int Graham_Scan(){    int i;    int p0 = 0;    for(i = 1;i < N;i++)        //选出最低点    {        if(farms[p0].y > farms[i].y||(farms[p0].y == farms[i].y&&farms[p0].x > farms[i].x))        {            p0 = i;        }    }    convexNum = 0;    swap(farms[0],farms[p0]);    sort(farms+1,farms+N,cmp);    convex[convexNum++] = farms[0];     //最低点肯定属于凸包    convex[convexNum++] = farms[1];    for(i = convexNum;i < N;i++)    {        while(convexNum != 1&&crossMult(convex[convexNum-2],convex[convexNum-1],farms[i]) <= 0)    //因为没有剔除共线情况,第2个点convex[1]也可能更新            convexNum--;        convex[convexNum++] = farms[i];    }    return 0;}int RC(){    int i;    int maxDis = calcDis(convex[0],convex[1]);    int maxP = 1;    for(i = 0;i < convexNum;i++)    {        while(crossMult(convex[i],convex[(i+1)%convexNum],convex[(maxP+1)%convexNum]) > crossMult(convex[i],convex[(i+1)%convexNum],convex[maxP]))            maxP = (maxP+1)%convexNum;        maxDis = max(maxDis,max(calcDis(convex[maxP],convex[i]),calcDis(convex[maxP],convex[(i+1)%convexNum])));    }    printf("%d\n",maxDis);    return 0;}int main(){    int i;    while(~scanf("%d",&N))    {        for(i = 0;i < N;i++)            scanf("%d%d",&farms[i].x,&farms[i].y);        if(N == 2)        {            printf("%d\n",calcDis(farms[0],farms[1]));            continue;        }        Graham_Scan();        RC();    }    return 0;}


0 0