bzoj 1069 凸包+旋转卡壳

题目大意

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

分析

枚举对角线的一个端点
另一个端点开始转
转的时候求出对角线左边面积最大的三角形,右边面积最大的三角形
三角形面积\(=\)对角线长度\(*\)
\(=\)两条平行线间任意两点距离
过对角线做两条平行线,对着凸包夹一夹
可以发现这实际上就是一个旋转卡壳
\(O(n^2)\)

solution
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
typedef long double db ;
using namespace std;
const int M=2007;

struct pt{
    db x,y;
    pt(db xx=0.0,db yy=0.0){x=xx;y=yy;}
}p[M],s[M];
pt operator -(pt x,pt y){return pt(x.x-y.x,x.y-y.y);}
pt operator +(pt x,pt y){return pt(x.x+y.x,x.y+y.y);}
bool operator <(pt x,pt y){if(x.y!=y.y)return x.y<y.y; return x.x<y.x;}
db cross(pt x,pt y){
    return x.x*y.y-x.y*y.x;
}
db dot(pt x,pt y){
    return x.x*y.x+x.y*y.y;
}
db area(pt x,pt y,pt z){
    return cross(y-x,z-x);
}
db length(pt x){
    return sqrt(dot(x,x));
};
db shadow(pt x,pt to){
    return dot(x,to)/length(to);
}

bool cmp(pt x,pt y){//ÄæʱÕ뼫½ÇÅÅÐò 
    db tp=area(p[1],x,y);
    if(tp==0) return length(x-p[1])<length(y-p[1]);
    return tp>0;    
}

int n;

int tot;

void convex(){
    int ii=1,i;
    for(i=1;i<=n;i++) if(p[i]<p[ii]) ii=i;
    swap(p[1],p[ii]);
    sort(p+2,p+n+1,cmp);
    
    s[tot=1]=p[1];
    for(i=2;i<=n;i++){
        while(tot>1&&area(s[tot-1],s[tot],p[i])<=0) tot--;//  <=  
        s[++tot]=p[i];
    } 
}

int main(){
    int i,j,k,p1,p2;
    db x,y;
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        scanf("%Lf%Lf",&x,&y);
        p[i]=pt(x,y);
    }
    
    convex();
    
    db ans=0;
    for(i=1;i<tot;i++){
        p1=i,p2=i+1;
        for(j=i+1;j<=tot;j++){
            while(area(s[i],s[p1],s[j])<area(s[i],s[p1%tot+1],s[j])) p1=p1%tot+1;
            while(area(s[i],s[j],s[p2])<area(s[i],s[j],s[p2%tot+1])) p2=p2%tot+1;
            ans=max(ans,area(s[i],s[p1],s[j])+area(s[i],s[j],s[p2]));
        }
    }
    
    printf("%.3Lf\n",ans/2.0);

    return 0;
}

转载于:https://www.cnblogs.com/acha/p/6429336.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值