题目链接
http://www.lydsy.com/JudgeOnline/problem.php?id=2338
思路
一个很显然的 O(n4)做法是枚举矩形abcd的四个顶点,然后判定矩形是否合法,求出矩形的面积,然后再更新答案 ,这个做法很麻烦,而且很慢,有一个 O(n2)的做法,因为矩形的两个对角线相等且相互平分,因此可以O(n2)找出所有的线段,然后O(nlogn)给线段按照线段的中点进行排序,再O(n2)枚举矩形的两条对角线即可更新答案。这里为了避免卡精度,可以避开浮点运算,两点间的距离不开根、求中点时不除以2就行了
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <cmath>
#define MAXN 1520
using namespace std;
typedef long long int LL;
int n;
struct Point
{
LL x,y;
Point(){}
Point(LL _x,LL _y) : x(_x),y(_y){}
}points[MAXN];
bool operator==(Point a,Point b)
{
return a.x==b.x&&a.y==b.y;
}
bool operator<(Point a,Point b)
{
if(a.x==b.x) return a.y<b.y;
return a.x<b.x;
}
bool operator>(Point a,Point b)
{
if(a.x==b.x) return a.y>b.y;
return a.x>b.x;
}
Point operator+(Point a,Point b)
{
return Point(a.x+b.x,a.y+b.y);
}
Point operator-(Point a,Point b)
{
return Point(a.x-b.x,a.y-b.y);
}
LL operator*(Point a,Point b)
{
return a.x*b.y-a.y*b.x;
}
struct Line
{
int a,b; //线段的两个端点
LL len;
Point mid;
Line(){}
Line(int _a,int _b,LL _len,Point _mid):a(_a),b(_b),len(_len),mid(_mid){}
}lines[MAXN*MAXN];
int cnt=0; //对角线总数
LL dist(Point a,Point b) //求点a与点b之间的距离
{
return (LL)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
LL max(LL a,int b)
{
if(a>b) return a;
return b;
}
bool operator==(Line a,Line b)
{
return a.len==b.len&&a.mid==b.mid;
}
bool operator<(Line a,Line b)
{
if(a.len==b.len) return a.mid<b.mid;
return a.len<b.len;
}
int main()
{
LL ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld%lld",&points[i].x,&points[i].y);
for(int i=1;i<n;i++)
for(int j=i+1;j<=n;j++)
lines[++cnt]=Line(i,j,dist(points[i],points[j]),points[i]+points[j]);
sort(lines+1,lines+cnt+1);
for(int i=1;i<=cnt;i++)
for(int j=i-1;j&&lines[i]==lines[j];j--) //为了不重复计算,只数下标小于i的那部分对角线
ans=max(ans,abs((points[lines[i].a]-points[lines[j].a])*(points[lines[i].a]-points[lines[j].b])));
printf("%lld\n",ans);
return 0;
}