您的位置:首页 > 其它

bzoj1069 [SCOI2007]最大土地面积(凸包+旋转卡壳)

2017-12-09 23:01 435 查看

bzoj1069 [SCOI2007]最大土地面积

原题地址http://www.lydsy.com/JudgeOnline/problem.php?id=1069

题意:

在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成的多边形面积最大。

数据范围

n<=2000, |x|,|y|<=100000

题解:

首先,发现这四个点肯定都在凸包上,因为倘若一个点不在凸包上,肯定可以让凸包上一个点代替它,使面积更大。

暴力枚举4个点肯定是不行的。

于是考虑枚举对角线,然后寻找对角线两侧可以取到的最大三角形。

如果固定一个点,顺时针枚举对角线的另外一个点,发现与他们组成四边形的另两个点也是在顺时针移动的。

(想像用与枚举的整条对角线在两侧去卡这个凸包)

于是这是O(n^2)的。

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#define Poi Vec
using namespace std;
const double EPS=1e-8;
const int N=2005;
struct Vec
{
double x,y;
Vec(double x=0.0,double y=0.0):x(x),y(y) {}
}P
,cvx
;
Vec operator+(const Vec &A,const Vec &B) {return Vec(A.x+B.x,A.y+B.y);}
Vec operator-(const Vec &A,const Vec &B) {return Vec(A.x-B.x,A.y-B.y);}
Vec operator*(const Vec &A,double s) {return Vec(A.x*s,A.y*s);}
Vec operator/(const Vec &A,double s) {return Vec(A.x/s,A.y/s);}
double cross(const Vec &A,const Vec &B) {return A.x*B.y-B.x*A.y;}
double dot(const Vec &A,const Vec &B) {return A.x*B.x+A.y*B.y;}
bool cmp(const Vec &A,const Vec &B) {return (A.x!=B.x)?A.x<B.x:A.y<B.y;}
bool onleft(Poi A,Poi B,Poi C) {return cross(B-A,C-A)>0;}
int n,nxt
;
int getcvx()
{
sort(P,P+n,cmp);
int t=0; cvx[0]=P[0];
for(int i=1;i<n;i++)
{
while(t>0&&!onleft(cvx[t-1],cvx[t],P[i])) t--;
cvx[++t]=P[i];
}
int h=t;
for(int i=n-2;i>=0;i--)
{
while(t>h&&!onleft(cvx[t-1],cvx[t],P[i])) t--;
cvx[++t]=P[i];
}
if(n>1) t--;
return t+1;
}
double getarea(Poi A,Poi B,Poi C) {return fabs(cross(B-A,C-A))/2.0;}
double getpoly()
{
if(n<=2) return 0;
else if(n==3) return getarea(cvx[0],cvx[1],cvx[2]);
double ans=0.0;
for(int i=0;i<n;i++) nxt[i]=(i+1)%n;
for(int i=0;i<n;i++)
{
for(int j=((i+1)%n+1)%n,a=(i+1)%n,b=(j+1)%n;(j+1)%n!=i;j=(j+1)%n)///
{
while(getarea(cvx[i],cvx[a],cvx[j])<getarea(cvx[i],cvx[(a+1)%n],cvx[j])) a=(a+1)%n;
while(getarea(cvx[j],cvx[b],cvx[i])<getarea(cvx[j],cvx[(b+1)%n],cvx[i])) b=(b+1)%n;
ans=max(ans,getarea(cvx[i],cvx[a],cvx[j])+getarea(cvx[j],cvx[b],cvx[i]));
}
}
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++) {double x,y; scanf("%lf%lf",&x,&y); P[i]=Vec(x,y);}
n=getcvx();
double ans=getpoly();
printf("%0.3lf\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: