首页 > 代码库 > BZOJ 2338 HNOI 2011 数矩形 计算几何

BZOJ 2338 HNOI 2011 数矩形 计算几何

题目大意:给出平面上的一些点,求这些点中组成的矩形的最大面积。


思路:任意找四个点然后判断肯定是不行的,那么我们不妨来想一想矩形的性质。比如,对角线的交点是两条对角线的中点,对角线相等。这样的话只要找到一对线段,使得他们的中点相同,并且长度相同,那么这两个对角线一定能够组成一个矩形。只有就可以利用叉积求出面积了。

比较坑的一点是,这个题万万不能用double,因为有一个点专门卡double。可以尝试用long double,最好还是避免精度问题,统一用整数。


CODE:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 1600
using namespace std;
 
struct Point{
    long long x,y;
     
    Point(long long _ = 0,long long __ = 0):x(_),y(__) {}
    bool operator <(const Point &a)const {
        if(x == a.x)    return y < a.y;
        return x < a.x;
    }
    Point operator -(const Point &a)const {
        return Point(x - a.x,y - a.y);
    }
    bool operator ==(const Point &a)const {
        return (x == a.x && y == a.y);
    }
    void Read() {
        scanf("%lld%lld",&x,&y);
    }
}point[MAX];
struct Segment{
    Point a,b;
    Point bi_mid;
    long long length;
     
    Segment(Point _,Point __):a(_),b(__) {
        Point temp = a - b;
        length = temp.x * temp.x + temp.y * temp.y;
        bi_mid.x = a.x + b.x;
        bi_mid.y = a.y + b.y;
    }
    Segment() {}
    bool operator <(const Segment &a)const {
        if(length == a.length)  return bi_mid < a.bi_mid;
        return length < a.length;
    }
}segment[MAX * MAX >> 1];
 
int points,segments;
 
inline long long Cross(const Point &a,const Point &b);
inline long long Work(const Segment &a,const Segment &b);
 
int main()
{
    cin >> points;
    for(int i = 1;i <= points; ++i)
        point[i].Read();
    for(int i = 1;i <= points; ++i)
        for(int j = i + 1;j <= points; ++j)
            segment[++segments] = Segment(point[i],point[j]);
    sort(segment + 1,segment + segments + 1);
    long long ans = 0;
    for(int i = 1;i <= segments; ++i) {
        int start = i,end = i;
        while(segment[end + 1].length == segment[start].length && segment[end + 1].bi_mid == segment[start].bi_mid)
            ++end;
        for(int j = start;j <= end; ++j)
            for(int k = j + 1;k <= end; ++k)
                ans = max(ans,Work(segment[j],segment[k]));
        i = end;
    }
    cout << ans << endl;
    return 0;
}
 
inline long long Cross(const Point &a,const Point &b)
{
    return a.x * b.y - a.y * b.x;
}
 
inline long long Work(const Segment &a,const Segment &b)
{
    Point p1 = b.a - a.a,p2 = b.b - a.a;
    return abs(Cross(p1,p2));
}


BZOJ 2338 HNOI 2011 数矩形 计算几何