Description
2维平面上有n个木桩,黄学长有一次圈地的机会并得到圈到的土地,为了体现他的高风亮节,他要使他圈到的土地面积尽量小。圈地需要圈一个至少3个点的多边形,多边形的顶点就是一个木桩,圈得的土地就是这个多边形内部的土地。(因为黄学长非常的神,所以他允许圈出的第n点共线,那样面积算0)
Input
第一行一个整数n,表示木桩个数。
接下来n行,每行2个整数表示一个木桩的坐标,坐标两两不同。
Output
仅一行,表示最小圈得的土地面积,保留2位小数。
Sample Input
3
0 0
0 1
1 0
Sample Output
0.50
Hint
对于100%的数据,n<=1000。
题意:给n个点,问任意三个点构成三角形的最小面积
思路:把所有可以连成的直线按斜率从小到大排序,枚举直线作为三角形底边,用最接近直线的左右两个点更新答案。关键是如何O(1)查到离直线最近的两个点,这里我们先把所有点按x为第一关键字升序,y为第二关键字升序排列,pos[i]表示原来编号为 i 的点现在的编号,id[i]表示现在的编号 i 对应之前的哪个点,在枚举相邻两条直线l1、l2前后,和l2距离的相对顺序改变的只有l1的两个端点,因为如果有别的点对相对顺序改变,这条直线的斜率一定介于l1、l2之间,矛盾。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3 + 7;
const int M = 1e6 + 7;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
struct Point {
double x, y;
int i, j;
Point() { x = y = 0; }
Point(double a, double b) { x = a, y = b; }
Point(double a, double b, Point p) { i = a, j = b, x = p.x, y = p.y; }
Point operator - (const Point &n) const {
return Point(x - n.x, y - n.y);
}
bool operator < (const Point &n) const {
return x == n.x ? y < n.y : x < n.x;
}
} p[N];
struct Line {
int s, t;
double k;
bool operator < (const Line &a) const {
return k < a.k;
}
} l[M];
double cross(Point a, Point b) {
return 1ll * a.x * b.y - 1ll * a.y * b.x;
}
double cal(Point P, Line L) {
return 0.5 * fabs(cross((p[L.s] - P), (p[L.t] - P)));
}
int pos[N], id[N];
int main() {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++i) scanf("%lf%lf", &p[i].x, &p[i].y);
sort(p + 1, p + n + 1);
for(int i = 1; i <= n; ++i) pos[i] = id[i] = i;
int tot = 0;
for(int i = 1; i <= n; ++i) {
for(int j = i + 1; j <= n; ++j) {
double k;
if(p[i].x == p[j].x) k = 1.0 * inf;
else k = 1.0 * (p[i].y - p[j].y) / (p[i].x - p[j].x);
l[++tot] = Line{i, j, k};
}
}
sort(l + 1, l + tot + 1);
double ans = 1.0 * inf;
for(int i = 1; i <= tot; ++i) {
int x = pos[l[i].s], y = pos[l[i].t];
if(x > y) swap(x, y);
if(x > 1) ans = min(ans, cal(p[id[x - 1]], l[i]));
if(y < n) ans = min(ans, cal(p[id[y + 1]], l[i]));
swap(pos[l[i].s], pos[l[i].t]);
swap(id[x], id[y]);
}
printf("%.2f\n", ans);
return 0;
}