题目:https://pintia.cn/problem-sets/994805046380707840/problems/994805046577840128
在古老的迈瑞城,巍然屹立着 n 块神石。长老们商议,选取 3 块神石围成一个神坛。因为神坛的能量强度与它的面积成反比,因此神坛的面积越小越好。特殊地,如果有两块神石坐标相同,或者三块神石共线,神坛的面积为 0.000。
n是5000;
输出格式:
在一行中输出神坛的最小面积,四舍五入保留 3 位小数。
解决办法:
枚举每一个点当极坐标的原点,求其它点相对于这个i点的位置,也可以理解为向量,然后再按照叉积排序,最后相邻的俩个相邻就是最小的,遍历所有相邻的就ok。
#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
//#include<bits/stdc++.h>
#define PII pair<int, int>
//#define x first
//#define y second
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int N = 5000 + 7;
using namespace std;
struct Point { //存点
ll x, y; //这里必须用ll,double在下面的运算中会爆掉
Point() {}
Point(ll x, ll y) : x(x), y(y){};
Point operator+(Point A) { return Point(x + A.x, y + A.y); }
Point operator-(Point A) { return Point(x - A.x, y - A.y); }
bool operator<(const Point &A) const { return x * A.y - y * A.x > 0; }
} P[N], Q[N]; //P存点,Q用来存极坐标点(可以理解为向量)
ll Cross(Point A, Point B) { return A.x * B.y - A.y * B.x; }//求叉积
int main(int argc, char const *argv[]) {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%lld%lld", &P[i].x, &P[i].y);
}
double minn = INF;
for (int i = 1; i <= n; i++) {
int tol = 0;
for (int j = 1; j <= n; j++) { //把相对于i点的极坐标都求出来,即向量
if (i != j) Q[++tol] = P[j] - P[i];
}
sort(Q + 1, Q + 1 + tol); //按照叉积排序
for (int j = 1; j < tol; j++) {
// if (Cross(Q[j], Q[j + 1])<0)printf("100\n"); //排完以后叉积没有小于0的了,放开交了一发也A了
minn = min(minn, fabs(Cross(Q[j], Q[j + 1])) * 0.5); //相邻俩个即最小
}
minn = min(minn,fabs(Cross(Q[1],Q[tol]))*0.5); //这一条好像不加也能A
}
printf("%.3lf\n", minn);
return 0;
}