POJ 2187 Beauty Contest | 旋转卡壳

题目:

给n个点,输出距离最远的一对点的距离的平方


题解:

旋转卡壳模板!

首先可以肯定的是最远的点一定是凸包的一对顶点!(这个正确性是很显然的)

所以我们枚举每个顶点所在的边,将它平移,平移到经过的最远一个点就是含有这个点的最远距离

所以N2是可以解决的!

但是这个和枚举点是没区别的.

但是如果我们逆时针枚举边的话,最远点变化也是逆时针的,所以接着上次的算就好啦.这样就优化到O(n)

具体实现的话可以叉积用面积算

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 50005
using namespace std;
int n,m;
void chkmax(int &a,const int &b)
{
    if (a<b) a=b;
}
struct point
{
    int x,y;
    point () {};
    point (int _x,int _y)
	{
	    x=_x,y=_y;
	}
    point operator - (const point &a) const
	{
	    return point(x-a.x,y-a.y);
	}
    int operator * (const point &a)const
	{
	    return x*a.y-y*a.x;
	}
    int norm() const
	{
	    return x*x+y*y;
	}
}p[N],q[N];
bool cmp(int u,int v)
{
    int det=(p[u]-p[1])*(p[v]-p[1]);
    if (det!=0) return det>0;
    return (p[u]-p[1]).norm()<(p[v]-p[1]).norm();
}
void Graham()
{
    int id=1;
    for (int i=2;i<=n;i++)
	if (p[i].x<p[id].x || (p[i].x==p[id].x && p[i].y<p[id].y))
	    id=i;
    if (id!=1) swap(p[1],p[id]);
    int per[N];
    for (int i=1;i<=n;i++) per[i]=i;
    sort(per+2,per+1+n,cmp);
    q[++m]=p[1];
    for (int i=2;i<=n;i++)
    {
	int j=per[i];
	while (m>=2 && (p[j]-q[m-1])*(q[m]-q[m-1])>=0)
	    m--;
	q[++m]=p[j];
    }
}

int Area(const point &x,const point &y,const point &z)
{
    return (y-x)*(z-x);
}
int nxt(int x)
{
    return x==m?1:x+1;
}
int solve()
{
    if (m==2) return (q[2]-q[1]).norm();
    int res=0;
    q[m+1]=q[1];
    for (int i=1,j=3;i<=m;i++)
    {
	while (nxt(j)!=i && Area(q[i],q[i+1],q[j])<=Area(q[i],q[i+1],q[j+1]))
	    j=nxt(j);
	chkmax(res,(q[j]-q[i]).norm());
	chkmax(res,(q[j]-q[i+1]).norm());
    }
    return res;
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
	scanf("%d%d",&p[i].x,&p[i].y);
    Graham();
    printf("%d\n",solve());
    return 0;
}

 

 

 

posted @ 2017-12-13 14:11  MSPqwq  阅读(140)  评论(0编辑  收藏  举报