题目描述
在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成
的多边形面积最大。
Input
第1行一个正整数N,接下来N行,每行2个数x,y,表示该点的横坐标和纵坐标。
Output
最大的多边形面积,答案精确到小数点后3位。
Sample Input
5
0 0
1 0
1 1
0 1
0.5 0.5
Sample Output
1.000
题解
这道题目就是给你一个点集,问你选4个点能构成的最大四边形面积为多少。
首先这四个点肯定都在凸包上,否则答案肯定不是最优的。
然后我们就可以用旋转卡壳去做了,我们可以枚举一条对角线,然后在左半部分和右半部分分别求出面积最大的三角形即可。
至于怎么求面积最大的三角形,大家可以看我的另一篇博客:戳这里
这道题目就讲完了,如果还没有理解的,大家可以看看我的代码。
下面贴代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 2010
using namespace std;
struct P{
double x,y;
}p[maxn];
P operator - (P a,P b)
{
P tmp;
tmp.x=a.x-b.x;
tmp.y=a.y-b.y;
return tmp;
}
double operator * (P a,P b)
{
return a.x*b.y-b.x*a.y;
}
double dist(P a,P b)
{
P tmp=a-b;
return sqrt(tmp.x*tmp.x+tmp.y*tmp.y);
}
bool cmp(P p1,P p2)
{
double s=(p1-p[1])*(p2-p[1]);
return s>0||(s==0&&dist(p1,p[1])>=dist(p2,p[1]));
}
bool judge(int p0,int p1,int p2)
{
double s=(p[p1]-p[p0])*(p[p2]-p[p0]);
return s>0||(s==0&&dist(p[p1],p[p0])>=dist(p[p2],p[p0]));
}
double S(P p1,P p2,P p3)
{
double l1=dist(p1,p2),l2=dist(p2,p3),l3=dist(p3,p1);
double ar=(l1+l2+l3)/2;
return sqrt(ar*(ar-l1)*(ar-l2)*(ar-l3));
}
int n;
int q[maxn],top;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
int fir=1;
for(int i=2;i<=n;i++)
{
if(p[i].y<p[fir].y||(p[i].y==p[fir].y&&p[i].x<p[fir].x)){
fir=i;
}
}
swap(p[fir],p[1]);
sort(p+2,p+n+1,cmp);
p[n+1]=p[1];
q[++top]=1;q[++top]=2;
for(int i=3;i<=n+1;i++)
{
while(top>1&&judge(q[top-1],i,q[top])==true) top--;
q[++top]=i;
}
top--;
double ans=0;
for(int i=1;i<=top;i++)
{
int a=i%top+1,b=(i+2)%top+1;//a,b为两个指针
for(int j=i+2;j<=top;j++)
{
while(a%top+1!=j&&(p[q[a]]-p[q[i]])*(p[q[j]]-p[q[i]])<(p[q[a+1]]-p[q[i]])*(p[q[j]]-p[q[i]])){
a=a%top+1;//答案比较
}
while(b%top+1!=i&&(p[q[j]]-p[q[i]])*(p[q[b]]-p[q[i]])<(p[q[j]]-p[q[i]])*(p[q[b+1]]-p[q[i]])){
b=b%top+1;//同上
}
ans=max(ans,S(p[q[i]],p[q[j]],p[q[a]])+S(p[q[i]],p[q[j]],p[q[b]]));//计算答案
}
}
printf("%.3lf\n",ans);
return 0;
}
谢谢大家!!