题目
- 给定若干个点,从这些点里面选取4个点构成一个矩形,使得矩形面积最大
- 原题链接:点这里
算法思路
思路
- 对于一个矩形,给定他的两条对角线一定长度相等,且有,中点相等
- 故我们可以通过枚举两个点,得到对角线,再排序过后,对相同的长度,相同中点的对角线处理
- 知道对角线的向量,即可求出矩形的面积
实现细节
- 本题为了避免出现浮点数,用LL代替double,我们把所有的中点都乘以2,这样就可以只用LL表示中点,避免了精度带来的误差
- 以及计算距离的时候,用平方来表示原来的数
- 该题的关键就是自定义排序,让相同的长度,相同中点的对角线聚在一起,方便处理
复杂度分析
- 原本没有想到最坏的情况,看到洛谷题解的评论才想到的
- 构造一个圆的情况,但是据说圆上最多只有400个点?(如果是1500个点就可以卡掉,
O
(
n
3
)
O(n^3)
O(n3))
- 因为他是整点,不可能1500个点全部都在同一个圆上
- 枚举对角线
O
(
n
2
)
O(n^2)
O(n2),排序
O
(
n
2
log
n
2
)
O(n^2 \log n^2)
O(n2logn2),还有一个三层循环的玄学复杂度……不会分析,反正可以理解为上界特别松
代码实现
#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>
using namespace std;
#define debug(x) cerr << #x << ": " << x << '\n'
#define bd cerr << "----------------------" << el
#define el '\n'
#define cl putchar('\n')
#define pb push_back
#define eb emplace_back
#define x first
#define y second
#define rep(i, a, b) for (int i = (a); i <= (b); i++)
#define loop(i, a, b) for (int i = (a); i < (b); i++)
#define dwn(i, a, b) for (int i = (a); i >= (b); i--)
#define ceil(a, b) (a + (b - 1)) / b
#define ms(a, x) memset(a, x, sizeof(a))
#define inf 0x3f3f3f3f
#define db double
typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<db, db> PDD;
typedef pair<LL, LL> PLL;
typedef vector<int> vci;
typedef map<int, int> mii;
typedef mii::iterator mii_it;
const int N = 1500 + 10, M = 2e6 + 10, E = 1e3 + 10, md = 1e9 + 7;
const double PI = acos(-1), eps = 1e-8;
int T, n, m;
LL operator * (PLL a, PLL b)
{
return a.x * b.y - a.y * b.x;
}
PLL operator + (PLL a, PLL b)
{
return {a.x + b.x, a.y + b.y};
}
PLL operator - (PLL a, PLL b)
{
return {a.x - b.x, a.y - b.y};
}
PLL p[N];
struct Segment
{
PLL v, midp;
LL len;
}s[N*N];
int tot;
LL get_dist(int i, int j)
{
return (p[i].x - p[j].x) * (p[i].x - p[j].x)
+ (p[i].y - p[j].y) * (p[i].y - p[j].y);
}
bool cmp(Segment a, Segment b)
{
if(a.len == b.len)
return a.midp < b.midp;
else
return a.len > b.len;
}
int main()
{
cin.tie(0);
cout.tie(0);
cin >> n;
rep(i, 1, n)
{
cin >> p[i].x >> p[i].y;
loop(j, 1, i)
s[ ++ tot] = {p[i] - p[j], p[i] + p[j], get_dist(i, j)};
}
sort(s + 1, s + tot + 1, cmp);
LL ans = 0;
for (int i = 1, j = 1; i <= tot; i = j)
{
while(s[i].len == s[j].len && s[i].midp == s[j].midp)
j ++ ;
loop (k, i, j)
loop (t, k + 1, j)
ans = max(ans, abs(s[k].v * s[t].v) >> 1);
}
cout << ans;
}