POJ2187 Beauty Contest

题意:N个平面点,求两点之间距离最大值


分析:简单题

旋转卡壳算法求凸包的直径

附一个很优秀的博客:点击打开链接


代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;

struct Point{
   int x,y;
   Point (int x=0, int y=0):x(x),y(y){}
};

typedef Point Vector;

Vector operator +(Vector A,Vector B) { return Vector(A.x+B.x,A.y+B.y); }
Vector operator -(Vector A,Vector B) { return Vector(A.x-B.x,A.y-B.y); }
Vector operator *(Vector A,double p) { return Vector(A.x*p,A.y*p); }

int Dot(Vector A,Vector B) { return A.x*B.x+A.y*B.y; }
int Cross(Vector A,Vector B) { return A.x*B.y-A.y*B.x; }
int Length(Vector A) { return Dot(A,A); }

const int maxn = 50000+10;
Point p[maxn],sol[maxn];
int n,m;

bool cmp(Point a, Point b){
   int ans = Cross(a-p[0],b-p[0]);
   return ans>0 || ans==0 && Length(a-p[0])<Length(b-p[0]);
}

int ConvexHull(Point *p,Point *ch){
    sort(p+1,p+n,cmp);
    int m = 0;
    for (int i=0; i<n; i++) {
        while (m>1 && Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
        ch[m++] = p[i];
    }

    int k = m;
    for (int i=n-2; i>=0; i--){
        while (m>k && Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
        ch[m++] = p[i];
    }

    if (n>1) m--;
    return m;
}

int Rotate_calipers(Point* ch, int n){
    int q=1;
    int ans = 0;
    ch[n] = ch[0];
    for (int i=0; i<n; i++) {
        while ( Cross(ch[q+1]-ch[i],ch[q+1]-ch[i+1])>Cross(ch[q]-ch[i],ch[q]-ch[i+1]) ) q = (q+1)%n;
        ans = max( ans,max( Length(ch[i]-ch[q]),Length(ch[i+1]-ch[q+1]) ) );
    }
    return ans;
}

int main(){
    while (scanf("%d",&n)==1){
        int x,y;
        for (int i=0; i<n; i++) {
            scanf("%d%d",&x,&y);
            p[i] = Point(x,y);
        }

        if (n==2) {
            printf("%d\n",Length(p[0]-p[1]));
            continue;
        }

        for (int i=1; i<n; i++) {
            if (p[i].x<p[0].x || p[i].x==p[0].x && p[i].y<p[0].y) swap(p[i],p[0]);
        }

        //sort(p+1,p+n,cmp);
        //for (int i=0; i<n; i++) printf("%d %d\n",p[i].x,p[i].y);

        m = ConvexHull(p,sol);
        //printf("%d\n",m);
        printf("%d\n",Rotate_calipers(sol,m));

    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值