您的位置:首页 > 其它

[BZOJ 2338][HNOI 2011]数矩形(计算几何)

2015-02-22 10:54 525 查看

题目链接

http://www.lydsy.com/JudgeOnline/problem.php?id=2338

思路

一个很显然的O(n4)做法是枚举矩形abcd的四个顶点,然后判定矩形是否合法,求出矩形的面积,然后再更新答案O(n^4)做法是枚举矩形abcd的四个顶点,然后判定矩形是否合法,求出矩形的面积,然后再更新答案,这个做法很麻烦,而且很慢,有一个O(n2)的做法,因为矩形的两个对角线相等且相互平分,因此可以O(n2)找出所有的线段,然后O(nlogn)给线段按照线段的中点进行排序,再O(n2)枚举矩形的两条对角线即可更新答案。这里为了避免卡精度,可以避开浮点运算,两点间的距离不开根、求中点时不除以2就行了O(n^2)的做法,因为矩形的两个对角线相等且相互平分,因此可以O(n^2)找出所有的线段,然后O(nlogn)给线段按照线段的中点进行排序,再O(n^2)枚举矩形的两条对角线即可更新答案。这里为了避免卡精度,可以避开浮点运算,两点间的距离不开根、求中点时不除以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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: