2019.2.28更新:复杂度是O(n^2.5),证明见评论区,感谢 @HigHwindEx 指正
最近总是在找些水题做QAQ
说这个题之前,我想先说一些别的事…暑假集训的时候一个叫小兔子的同(神)学(犇)提出的问题:给出一堆点的坐标,求这些点所围成的正方形的个数(可以斜着)。
不得不说当时并没有怎么在意,结果前两天在noip吧里见到有普及组大神用n^3的算法解此题……然后我在回帖里找到了正解…顺便找到了此题……
这大概也是我做的第一个计算几何的题,当时并没有想这么多就开始写了,导致代码很难调所以重新打了一份,还写了个向量的加减之类的…
此题有O(n^2 logn)算法,做法是枚举n个点所构成的所有边O(n2),然后按第一关键字为中点坐标,第二关键字为边的长度进行排序(O(n2 logn)),初中生知识可知:中点相同并且长度相等的两条边必然是一个矩形的两条对角线。然后枚举计算即可。
一开始傻X一样double存,各种被误差恶心,然后成功溢出……顺便学会了long double…(scanf("%Lf",&a);)在codevs上交总是90分,感觉是精度有问题然后去百度…结果发现中点什么的只需要比较大小为何我要存浮点数(╯‵□′)╯︵┻━┻改成long long…各种恶心的浮点数问题就随之而去了……然后发现自己计算的时候没有计算完全,改了后A了。
第一次打计算几何的代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int size=1510;
struct point{
long long x,y;
long long dist()
{
return x*x+y*y;
}
}p[size];
point operator +(const point &a,const point &b)
{
return (point){a.x+b.x,a.y+b.y};
}
point operator -(const point &a,const point &b)
{
return (point){a.x-b.x,a.y-b.y};
}
bool operator ==(const point &a,const point &b)
{
return a.x==b.x&&a.y==b.y;
}
bool operator !=(const point &a,const point &b)
{
return (a.x!=b.x)||(a.y!=b.y);
}
bool operator <(const point &a,const point &b)
{
if(a.x!=b.x) return a.x<b.x;
return a.y<b.y;
}
struct edge{
point l,r,mid;
long long len;
}l[2250010];
bool operator <(const edge &a,const edge &b)
{
if(a.mid!=b.mid) return a.mid<b.mid;
return a.len<b.len;
}
int tot=0;
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&p[i].x,&p[i].y);
for(int j=1;j<i;j++)
{
l[++tot]=(edge){p[i],p[j],(p[i]+p[j]),((p[i]-p[j])).dist()};
}
}
// build(n);
sort(l+1,l+1+tot);
/* for(int i=1;i<=tot;i++)
{
int tot=i;
printf("%lld %lld %lld %lld %lld %lld %lld\n",l[tot].l.x,l[tot].l.y,l[tot].r.x,l[tot].r.y,l[tot].mid.x,l[tot].mid.y,l[tot].len);
}*/
long long ans=0;
for(int i=1,k=1;i<=tot;i++)
{
for(int j=k;j<i;j++)
if(l[i].mid==l[j].mid&&l[i].len==l[j].len)
{
ans=max(ans,(long long) ( sqrt( (l[i].l-l[j].l).dist() ) *sqrt( (long double) (l[i].l-l[j].r).dist() )+0.5) );
// puts("fuck");
}
else k=i;
}
printf("%lld",ans);
return 0;
}
/*
8
-2 3
-2 -1
0 3
0 -1
1 -1
2 1
-3 1
-2 1
*/