題目鏈接:
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.三點圍城的平面區域面積爲,即;
4.遍歷每一對排序後的相鄰向量,維護歷史面積最小值;
//複雜度約等於
代碼:
#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;
}