您的位置:首页 > 其它

POJ 2187(凸包GrahamScan扫描+极角排序+平面最远点对)

2013-01-18 11:54 218 查看
Language:
Default

平面最远点对

Time Limit: 3000MSMemory Limit: 65536K
Total Submissions: 22454Accepted: 6868
Description

求 N (2 <= N <= 50,000) 个点平面最远点对距离的平方.

Input

* 第1行:N

接下来每行为点的坐标 x 和 y ,(x,y)(-10,000<=x,y<=10,000的整数).

Output

输出一行,为平面最远点对距离平方.

Sample Input
4
0 0
0 1
1 1
1 0

Sample Output
2

Hint

(0, 0) a到 (1, 1) 距离平方为 2
Source

USACO 2003 Fall
凸包模版题:

先用GrahamScan扫描求凸包,显然最远点对在凸包上。

极角排序:

按照逆时针顺序给平面上的点集到一个点的距离排序,使得排序后所有点正好绕这个点一圈.(按距离远近从小到大排

思路:



GrahamScan扫描:



















大致如此.

另补:

该题小Bug-有可能所有点在一条直线上。

这样也能求出:

Ex:

a序列(-1,0) (0,0) (4,0) (9,0)

则st序列重复如下操作:

(-1,1),(0,0)入队。

(4,0)入队,不左拐->(0,0)出队

队列元素<2 (4,0)入队

……

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define MAXN (50000+10)
double sqr(double x){return x*x;}
struct P
{
double x,y;
P(){}
P(double _x,double _y):x(_x),y(_y){}
}a[MAXN],st[MAXN];
int dis2(P A,P B)
{
return sqr(A.x-B.x)+sqr(A.y-B.y);
}
double dis(P A,P B)
{
return sqrt(double(dis2(A,B)));
}
struct V
{
double x,y;
V(){}
V(double _x,double _y):x(_x),y(_y){}
V(P A,P B):x(B.x-A.x),y(B.y-A.y){}
};
double operator*(V a,V b)
{
return a.x*b.y-a.y*b.x;
}
int cmp(P A,P B) //1:a>b 0:a<=b
{
double tmp=V(a[1],A)*V(a[1],B);
if (tmp>0) return 1;
else if (tmp==0) return (-(dis(a[1],A)-dis(a[1],B))>0)?1:0;
else return 0;
}
int n;
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) cin>>a[i].x>>a[i].y;
int p=1;
for (int i=2;i<=n;i++) if (a[i].x<a[p].x||a[i].x==a[p].x&&a[i].y<a[p].y) p=i;
if (p>1) swap(a[p],a[1]);
sort(a+2,a+1+n,cmp);

int size=1;
st[1]=a[1];
for (int i=2;i<=n;)
if (size<2||V(st[size-1],st[size])*V(st[size],a[i])>0)
st[++size]=a[i++];
else size--;

int ans=0;
for (int i=1;i<size;i++)
for (int j=i+1;j<=size;j++)
ans=max(ans,dis2(st[i],st[j]));
cout<<ans<<endl;

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: