题目链接:
https://pintia.cn/problem-sets/994805046380707840/problems/994805046577840128
思路:
1.一共n个点,对于每一个点我们都可以将它作为顶点,那么此点和其它n-1个点就会组成n-1个向量;
2.n-1个向量中,我们任意选取两个向量都可以满足“选取三块石头”这个条件,但是我们现在的目标是面积最小,因此我们需要对这n-1个向量进行极角排序;
(证明请参考https://blog.csdn.net/lixiangITA/article/details/88628713)
3. A , B , C A,B,C A,B,C三点围城的平面区域面积为 S = A B ⃗ × A C ⃗ 2 S=\frac{\vec{AB}\times\vec{AC}}{2} S=2AB×AC,即 A x ∗ B y − A y ∗ B x A_x*B_y-A_y*B_x Ax∗By−Ay∗Bx;
4.遍历每一对排序后的相邻向量,维护历史面积最小值;
//复杂度约等于 O ( n 2 log n ) O(n^2\log{n}) O(n2logn)
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5005;
ll x[maxn], y[maxn], ans = LLONG_MAX;
struct vec {
ll x, y;
bool operator < (const vec & a) const {
return x * a.y > y * a.x;
}
} v[maxn];
#define a_cross(a, b) abs(a.x * b.y - a.y * b.x)
int main() {
#ifdef MyTest
freopen("Sakura.txt", "r", stdin);
#endif
int n;
scanf("%d", &n);
for(int i = 0; i < n; ++i) scanf("%lld %lld", &x[i], &y[i]);
for(int i = 0; i < n; ++i) {
int tmp = 0;
for(int j = 0; j < n; ++j) {
if(i != j) v[tmp++] = vec{
x[j] - x[i], y[j] - y[i]};
}
sort(v, v + tmp);
for(int j = 1; j < tmp; ++j) {
ans = min(ans, a_cross(v[j - 1], v[j]));
}
}
printf("%.3f", 0.5 * ans);
return 0;
}