最大土地面积
时间限制: 5 Sec 内存限制: 128 MB
题目描述
在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成的多边形面积最大。
输入
第1行一个正整数N,接下来N行,每行2个数x,y,表示该点的横坐标和纵坐标。
输出
最大的多边形面积,答案精确到小数点后3位。
样例输入
5
0 0
1 0
1 1
0 1
0.5 0.5
样例输出
1.000
提示
数据范围 n<=2000, |x|,|y|<=100000
题解
凸包找点;
旋转卡壳枚举;
(写了一天总算写出来了~~~)
代码
#include <bits/stdc++.h>
using namespace std;
struct Point
{
double x,y;
};
Point a[2018],p[2018];
int n,tot,xxx;
double seita (Point p0,Point p1,Point p2)
{
return (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);
}
double get_len (Point p1,Point p2)
{
return sqrt((p2.y-p1.y)*(p2.y-p1.y)+(p2.x-p1.x)*(p2.x-p1.x));
}
bool cmp (Point p1,Point p2)
{
double temp = seita(p[0],p1,p2);
if(fabs(temp)<1e-6)
return get_len(p[0],p1)<get_len(p[0],p2);
else
return temp>0;
}
void graham ()
{
tot=2,xxx=0;
for(int i=0; i<n; ++i)
{
if(a[i].y<a[xxx].y||(a[i].y==a[xxx].y&&a[i].x<a[xxx].x))
xxx=i;
}
swap(a[0],a[xxx]);
p[0]=a[0];
sort(a+1,a+n,cmp);
p[1]=a[1],p[2]=a[2];
for(int i=3; i<n; ++i)
{
while(tot>0&&seita(p[tot-1],a[i],p[tot])>=0)
tot-=1;
tot++;
p[tot]=a[i];
}
}
double solve ()
{
double ans;
int x,b;
ans=0;
tot++;
for(int i=0; i<tot; ++i)
{
x=(i+1)%tot;
b=(i+3)%tot;
for(int j=i+2; j<tot; ++j)
{
while(x!=j&&fabs(seita(p[i],p[j],p[x+1]))>=fabs(seita(p[i],p[j],p[x])))
x=(x+1)%tot;
while(b!=i&&fabs(seita(p[i],p[j],p[b+1]))>=fabs(seita(p[i],p[j],p[b])))
b=(b+1)%tot;
ans=max(ans,fabs(seita(p[i],p[j],p[b]))+fabs(seita(p[i],p[j],p[x])));
}
}
return ans;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
scanf("%d",&n);
for(int i=0; i<n; ++i)
scanf("%lf %lf",&a[i].x,&a[i].y);
graham();
printf("%.3lf\n",solve()/2);
return 0;
}