这个题意思很清楚,求50000个点中距离最大的两个点,并输出最大距离,普通的o(n^2)是过不了的,正确的做法应该是利用凸包graham-scan(o(nlogn))扫描法缩小点集,然后用一个旋转卡壳的的算法(o(n))求出凸多边形的直径,但是当我在写旋转卡壳的时候wa了,我疯了,换了一个普通的二重循环居然过了,数据不强,要是那50000个点都为凸包的顶点就惨了。
1
/**//*
2
Name: pku2187
3
Copyright: ccnu
4
Author: Torres
5
Date: 11-08-08 15:08
6
Description: 利用凸包缩小点集求最大距离
7
*/
8
#include<iostream>
9
#include<cmath>
10
#include<algorithm>
11
using namespace std;
12
const double pi=acos(-1.0);
13
typedef struct point
{
14
double x,y;
15
point(double x=0,double y=0)
16
{this->x=x;this->y=y;}
17
}point;
18
int n;
19
point p[50005],ch[50005];
20
int top;
21
22
//p0p1 crossmul p0p2
23
double cross(point p0,point p1,point p2)
24

{return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);}
25
26
double dist(point a,point b)
27

{return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}
28
29
bool cmp(point a,point b)
30

{
31
double re=cross(p[0],a,b);
32
if(re>0)return true;
33
else if(!re&&dist(p[0],a)>dist(p[0],b))
34
return true;
35
else return false;
36
}
37
38
void graham(point a[])
39

{
40
int i,j=0;
41
for(i=1;i<n;i++)
42
if(a[i].y<a[j].y||a[i].y==a[j].y&&a[i].x<a[j].x)j=i;
43
swap(a[0],a[j]);//找出左下点
44
sort(a+1,a+n,cmp);
45
ch[0]=a[0];ch[1]=a[1];ch[2]=a[2];top=2;
46
for(i=3;i<n;i++)
{
47
while(cross(ch[top-1],a[i],ch[top])>=0)
48
{
49
top--;
50
if(top==1)break;
51
}
52
ch[++top]=a[i];//试探
53
}
54
}
55
int main()
56

{
57
int i,j;
58
int len=0;
59
scanf("%d",&n);
60
for(i=0;i<n;i++)
61
scanf("%lf%lf",&p[i].x,&p[i].y);
62
graham(p);
63
for(i=0;i<=top;i++)
64
for(j=0;j<=top;j++)
{
65
double temp=dist(ch[i],ch[j]);
66
if(len<temp)len=(int)temp;
67
}
68
printf("%d\n",len);
69
return 0;
70
}
71
72