poj 2187 求平面最远点对 快速凸包 旋转卡壳
毫无疑问,最远点对肯定都在土包上
所以可以先求凸包再两两枚举土包上的点
这时候的点会比原先情况下少很多
凸包用的是快速土包法
这种方法在有些时候会退化成N^2
英文例子:http://www.cs.princeton.edu/courses/archive/spr10/cos226/demo/ah/QuickHull.html
大牛博客:http://www.cnblogs.com/Booble/archive/2011/03/10/1980089.html
View Code
//快速土包算法,递归
#include <iostream>
#include <math.h>
#define maxn 100000
#define zero 1e-12
#define sgn(x) (fabs(x)<zero?0:(x>0?1:-1))
#define cross(a,b,c) ((b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x))
#define cmp(a,b) (a.x<b.x || sgn(a.x-b.x)==0 && a.y<b.y)
using namespace std;
struct point{
double x,y;
}p[maxn],convex_set[maxn];
double s[maxn];
int tot=1;
void hull(int l,int r,point a,point b){
int x=l,i=l-1,j=r+1,k;
for (k=l;k<=r;k++){
double temp=sgn(s[x]-s[k]);
if (temp<0 || temp==0 && cmp(p[x],p[k])) x=k;//找距离最远点
}
point y=p[x];
for (k=l;k<=r;k++){
s[++i]=cross(p[k],a,y);
if (sgn(s[i])>0) swap(p[i],p[k]); else i--;//划分点集
}
for (k=r;k>=l;k--){
s[--j]=cross(p[k],y,b);
if (sgn(s[j])>0) swap(p[j],p[k]); else j++;//划分点集
}
if (l<=i) hull(l,i,a,y);
convex_set[++tot]=y;
if (j<=r) hull(j,r,y,b);
}
double dis(point a,point b)
{
return ((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int main(){
int n,i,j,x=0;
scanf("%d",&n);
for (i=1;i<=n;i++){
scanf("%lf %lf",&p[i].x,&p[i].y);
if (x==0 || cmp(p[i],p[x])) x=i;
}
swap(p[1],p[x]);
convex_set[1]=p[1];
hull(2,n,p[1],p[1]);
double ans=0;
for(i=1;i<=tot;i++)
{
for(j=i+1;j<=tot;j++)
{
double tmp=dis(convex_set[i],convex_set[j]);
if(tmp>ans) ans=tmp;
}
}
printf("%.0lf\n",ans);
return 0;
}