题目链接:点我啊╭(╯^╰)╮
题目大意:
求二维平面内能组成的最大三角形面积
解题思路:
最大三角形肯定在凸包上
假设三个点为
i
,
p
,
q
i,p,q
i,p,q,枚举
i
i
i
固定
i
,
p
i,p
i,p 后,旋转
q
q
q,易得凸包是个单峰函数
所以在第一个下降的地方就是答案
然后固定
i
,
q
i,q
i,q,旋转
p
p
p,再求一遍答案
此时即找到三角形一点为
i
i
i 的最大面积
时间复杂度:
O
(
n
2
)
O(n^2)
O(n2)
为什么可以这样找?看了下别人的是继续枚举点 p p p,根据单调性使得 q q q 点一定只能往前移动,那么我的为什么是对的?希望有大佬解答一下。
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
const double eps = 1e-6;
const int maxn = 1e5 + 10;
int n;
struct point {
double x, y;
point(){}
point(double X, double Y){
x = X, y = Y;
}
point operator - (const point &A) {
return point(x-A.x, y-A.y);
}
bool operator < (const point &A)const {
if(x == A.x) return y < A.y;
return x < A.x;
}
} a[maxn], pa[maxn];
int dcmp(double x){
if(fabs(x) < eps) return 0;
return x < 0 ? -1 : 1;
}
double cross(point A, point B) { // 叉积
return A.x*B.y - B.x*A.y;
}
double xmult(point a, point b, point c){
return cross(a-c, b-c);
}
int andrew(point *P, int n, point *S) { // P为点集合, A为凸包点
sort(P, P+n);
int tp = 0;
for(int i=0; i<n; i++) { // 下凸包
while(tp>1 && dcmp(cross(S[tp-1]-S[tp-2], P[i]-S[tp-2]))<=0) tp--;
S[tp++] = P[i];
}
for(int i=n-2, k=tp; ~i; i--) { // 上凸包
while(tp>k && dcmp(cross(S[tp-1]-S[tp-2], P[i]-S[tp-2]))<=0) tp--;
S[tp++] = P[i];
}
return n > 1 ? tp - 1 : tp;
}
double rotating_calipers(int tp){
int p = 1, q = 2;
double ret = 0;
// pa[++tp] = pa[0];
for(int i=0; i<tp; i++){
while(xmult(pa[i], pa[p], pa[(q+1)%tp]) > xmult(pa[i], pa[p], pa[q]))
q = (q + 1) % tp; // i,p 固定,旋转 q
ret = max(ret, xmult(pa[i], pa[p], pa[q]));
while(xmult(pa[i], pa[(p+1)%tp], pa[q]) > xmult(pa[i], pa[p], pa[q]))
p = (p + 1) % tp; // i,q 固定,旋转 p
ret = max(ret, xmult(pa[i], pa[p], pa[q]));
}
return ret;
}
int main() {
while(~scanf("%d", &n) && n!=-1){
for(int i=0; i<n; i++) scanf("%lf%lf", &a[i].x, &a[i].y);
int tp = andrew(a, n, pa);
printf("%.2f\n", 0.5 * rotating_calipers(tp));
}
}