POJ 2187 Beauty Contest 旋转卡壳

题目大意:给定n个点,求距离最远的两个点之间的距离,输出最远距离的平方

旋转卡壳模板题。

#include <cstdio>
#include <algorithm>
#include <cstring>
#define N 50005
using namespace std;
inline int sq(int x) { return x*x; } //返回一个数的平方
struct Point {
    int x,y;
    Point(int _x=0,int _y=0):x(_x),y(_y) {}
    void scan() { scanf("%d%d",&x,&y); return ; }
    Point operator + (const Point& rhs) const { return Point(x+rhs.x,y+rhs.y); }
    Point operator - (const Point& rhs) const { return Point(x-rhs.x,y-rhs.y); }
    int operator * (const Point& rhs) const { return x*rhs.y-y*rhs.x; }//叉积
    int operator ^ (const Point& rhs) const { return x*rhs.x+y*rhs.y; }//点积
    int operator | (const Point& rhs) const { return sq(x-rhs.x)+sq(y-rhs.y); }//求两点间距离的平方
    bool operator < (const Point& rhs) const { return x<rhs.x || x==rhs.x && y<rhs.y; }//按照x为第一关键字,y为第二关键字比较大小
}p[N],q[N];
bool cmp(const Point& lhs,const Point& rhs) {
    int tmp=(lhs-p[1])*(rhs-p[1]);
    if(tmp!=0) return tmp>0;
    return (p[1]|lhs)<(p[1]|rhs);
}
int n,top;
//Graham扫描法求解凸包
void Graham() {
    int tmp=1;
    for(int i=2;i<=n;i++)
        if(p[i]<p[tmp])
            tmp=i;
    if(tmp!=1) swap(p[tmp],p[1]);
    q[++top]=p[1];
    sort(p+2,p+n+1,cmp); //从下标为2的位置开始极角排序
    for(int i=2;i<=n;i++) {
        while(top>1 && (p[i]-q[top-1])*(q[top]-q[top-1])>=0) top--;
        q[++top]=p[i];
    }
    return ;
}
int solve() {
    int ans=0;
    q[top+1]=q[1];
    int tmp=2;
    for(int i=1;i<=top;i++) {
        //旋转,以q[i+1]-q[i]为边,找距离最远的点
        while((q[i+1]-q[i])*(q[tmp]-q[i])<(q[i+1]-q[i])*(q[tmp+1]-q[i])) {
            tmp++;
            if(tmp==top+1) tmp=1;
        }
        ans=max(ans,q[tmp]|q[i]);
    }
    return ans;
}
int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;i++) p[i].scan();
    Graham();
    printf("%d\n",solve());
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值