poj 2187 Beauty Contest

Description

Bessie, Farmer John's prize cow, has just won first place in a bovine beauty contest, earning the title 'Miss Cow World'. As a result, Bessie will make a tour of N (2 <= N <= 50,000) farms around the world in order to spread goodwill between farmers and their cows. For simplicity, the world will be represented as a two-dimensional plane, where each farm is located at a pair of integer coordinates (x,y), each having a value in the range -10,000 ... 10,000. No two farms share the same pair of coordinates.

Even though Bessie travels directly in a straight line between pairs of farms, the distance between some farms can be quite large, so she wants to bring a suitcase full of hay with her so she has enough food to eat on each leg of her journey. Since Bessie refills her suitcase at every farm she visits, she wants to determine the maximum possible distance she might need to travel so she knows the size of suitcase she must bring.Help Bessie by computing the maximum distance among all pairs of farms.

Input

* Line 1: A single integer, N

* Lines 2..N+1: Two space-separated integers x and y specifying coordinate of each farm

Output

* Line 1: A single integer that is the squared distance between the pair of farms that are farthest apart from each other.

Sample Input


0 0 
0 1 
1 1 
1 0

Sample Output

2

Hint

Farm 1 (0, 0) and farm 3 (1, 1) have the longest distance (square root of 2)

Source



题目大意:给出平面上的n个点,找出距离最远的一对点,并输出它们距离的平方。

//=====================================================================================

隔了这么久又更新了、、开始了迟来的转C之旅、、、、

之前都是用C编模拟题好不欢乐这次尝试这题稍微有点算法的就跪了。。。不过也许是太久没有敲代码了错的全部都是思想细节和编程细节。。。。

好吧,,进入正题。。很明显这题就是用所谓的旋转卡壳求最远点对,因为数据范围根本不允许用平方的枚举。

关于旋转卡壳,主要的思想是求出所有对踵的距离,其中最大的即为所求。

至于证明,昨晚睡觉的时候YY了好久感觉正着想不太好理解啊。。也可能是因为没有纸笔全靠脑补。。于是,试着逆向想想,假设已知道最远点对,我们使一组平行线垂直于两点的连线,并使得两个点分别落在两条直线上。这时点集中剩下的点必然都落在平行线之间,不然必然可以找到更长的距离。(这个比较显然啊。。在平行线外的点到对面直线的距离肯定长更何况斜边。。)
poj <wbr>2187 <wbr>Beauty <wbr>Contest

如图a,b即两条平行线。

但是找一对对踵点并不容易。于是想到将这两条平行线同时旋转,它们必然会和相邻四条边中的一条(或者更多)重合,这样,我们就可以转换成找一条边和一个点。那么,这个点的有什么性质呢?它到这条边的距离最大。点到直线的距离最大可以用向量积很容易求出来。又因为是在凸包上找对踵点,于是最远点关于边的变化是单调的。于是复杂度降到了n。

在粗略的理了下算法后再讲讲细节。。如果两条边平行,那么对踵点找那个点呢?找先找到的点。也就是说在找距离当前边最远的点时把判断条件改为:当距离严格增加的时候才往下找。至于为什么呢?两条边平行,那么最远的距离肯定只能存在对角线中,于是。。找第二个肯定不会漏。。。这个。。。。。。自己YY下还是比较容易出来的吧。。。

WA了好多次最后发现。。。。快排编挫了。。。。

AC CODE

//刚写不久。。风格蒟蒻。。不喜勿喷。。

#include<cstdio>

#include<iostream>

using namespace std;

 

int x[60000]={0},y[60000]={0},stack[60000]={0};

int n,top=0;

 

void swap(int g,int h)

{

    int tmp=x[g]; x[g]=x[h]; x[h]=tmp;

    tmp=y[g]; y[g]=y[h]; y[h]=tmp;

}

 

int cha(int i,int j,int k)

{

    int tmp=(x[i]-x[k])*(y[j]-y[k])-(x[j]-x[k])*(y[i]-y[k]);

    return tmp;

}

 

int dist(int i,int j)

{

    int tmp=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);

    return tmp;

}

 

void init()

{

    int minx=32767,miny=32767,tmp;

    scanf("%d",&n);

    for (int i=1;i<=n;i++)

    {

        scanf("%d%d",&x[i],&y[i]);

        if (x[i]<minx)

        {

            minx=x[i];

            miny=y[i];

            tmp=i;

        } else

        if (x[i]==minx && y[i]<miny)

        {

            miny=y[i];

            tmp=i;

        }

    } swap(tmp,1);

    for (int i=2;i<=n;x[i]-=x[1],y[i]-=y[1],i++);

    x[1]=0; y[1]=0;

}

 

void polar_angle_sort(int l,int r)

{

    int k=(l+r)/2;

    x[n+1]=x[k]; y[n+1]=y[k];

    int i=l; int j=r;

    while (i<=j)

    {

        while (cha(i,n+1,1)>0 || (cha(i,n+1,1)==0 && dist(i,1)<dist(n+1,1))) i++;

        while (cha(j,n+1,1)<0 || (cha(j,n+1,1)==0 && dist(j,1)>dist(n+1,1))) j--;

        if (i<=j)

        {

            swap(i,j);

            i++; j--;

        }

    }

    if (l<j) polar_angle_sort(l,j);

    if (i<r) polar_angle_sort(i,r);

}

 

void tubao()

{

    for (int i=1;i<=n;i++)

    {

        if (top<2)

        {

            top++; stack[top]=i; continue;

        }

        while (top>1)

        {

            int tmp=cha(i,stack[top],stack[top-1]);

            if (tmp>=0) top--; else break;

        } top++; stack[top]=i;

    }

}

 

void distant()

{

    stack[top+1]=stack[1];

    int max=0,k=2;

    int p=stack[k],q=stack[k+1],tmp;

    for (int i=1; i<top; i++)

    {

        int j=i+1;

        int g=stack[i],h=stack[j];

        while (cha(h,p,g)<cha(h,q,g))

        {

            if (k<top) k++; else k=1;

            p=stack[k]; q=stack[k+1];

        }

        tmp=dist(g,p); if (tmp>max) max=tmp;

        tmp=dist(h,p); if (tmp>max) max=tmp;

    }

    printf("%d",max);

}

 

int main()

{

    init();

    polar_angle_sort(2,n);

    tubao();

    if (top==2)

        printf("%d",dist(stack[1],stack[2]));

    else distant();

    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值