您的位置:首页 > 其它

[凸包] BZOJ1069: [SCOI2007]最大土地面积

2017-06-29 20:09 399 查看

题意

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

n<=2000

题解

容易想到凸包。

最优的四边形的端点是落在凸包上的,然后n2枚举对角线。在对角线两侧类似旋转卡壳,利用单调性推得最大三角形。这样就是O(n2)的。

凸包是三角形?不知道啊反正没管就过了……之后才在discuss上看到,可能选凸包上3点,枚举第4个点可以..吧….

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=2005;
struct Point{
double x,y;
Point(double t1=0,double t2=0){ x=t1; y=t2; }
bool operator < (const Point &b)const{
if(x<b.x) return true;
if(x>b.x) return false;
return y<b.y;
}
} a[maxn],ch[maxn];
typedef Point Vector;
Vector operator + (Vector A,Vector B){ return Vector(A.x+B.x,A.y+B.y); }
Vector operator - (Point A,Point B){ return Vector(A.x-B.x,A.y-B.y); }
double Cross(Vector A,Vector B){ return A.x*B.y-A.y*B.x; }
int n,m;
double ans;
int Andrew(){
sort(a+1,a+n+1);
int len=0;
for(int i=1;i<=n;i++){
while(len>1&&Cross(ch[len]-ch[len-1],a[i]-ch[len-1])<0) len--;
ch[++len]=a[i];
}
int k=len;
for(int i=n-1;i>=1;i--){
while(len>k&&Cross(ch[len]-ch[len-1],a[i]-ch[len-1])<0) len--;
ch[++len]=a[i];
}
return len;
}
int main(){
freopen("bzoj1069.in","r",stdin);
freopen("bzoj1069.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y);
m=Andrew();
for(int i=0;i<=m-1;i++){
int k1=(i+1)%m,k2=(i+3)%m;
for(int j=(i+2)%m;(j+1)%m!=i;j=(j+1)%m){
while(Cross(ch[k1]-ch[i],ch[j]-ch[i])<Cross(ch[(k1+1)%m]-ch[i],ch[j]-ch[i])) k1=(k1+1)%m;
while(Cross(ch[k2]-ch[j],ch[i]-ch[j])<Cross(ch[(k2+1)%m]-ch[j],ch[i]-ch[j])) k2=(k2+1)%m;
ans=max(ans,Cross(ch[k1]-ch[i],ch[j]-ch[i])+Cross(ch[j]-ch[i],ch[k2]-ch[i]));
}
}
printf("%.3lf\n",ans/2);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: