【BZOJ1069】【SCOI2007】最大土地面积 凸包 单调性

来源:互联网 发布:欧洲卡车模拟2mac mod 编辑:程序博客网 时间:2024/05/21 14:44

链接:

#include <stdio.h>int main(){    puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢");    puts("网址:blog.csdn.net/vmurder/article/details/46591735");}

题解:

先求凸包,然后:

枚举点 i ,然后对于 点 j 得到的 ij (有序) 中间的点,以及 ji (有序) 中间的点,都是单调的。

代码:

#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 2050#define eps 1e-7using namespace std;struct Point{    double x,y;    void read(){scanf("%lf%lf",&x,&y);}    Point(double _x=0,double _y=0):x(_x),y(_y){}    bool operator < (const Point &A)const    {return x==A.x?y<A.y:x<A.x;}    double operator - (const Point &A)const    {return sqrt((x-A.x)*(x-A.x)+(y-A.y)*(y-A.y));}}p[N],Zero;int n;double xmul(const Point &A,const Point &B,const Point &C){return (C.y-A.y)*(B.x-A.x)-(B.y-A.y)*(C.x-A.x);}struct qiu_tu_bao{// 名字就是这么屌,不服你来打我啊    int stk1[N],top1,stk2[N],top2;    Point tp[N];    void work()    {        int i;        stk1[top1=1]=1;        for(i=2;i<=n;i++)        {            while(top1>1&&xmul(p[stk1[top1-1]],p[stk1[top1]],p[i])>-eps)top1--;            stk1[++top1]=i;        }        stk2[top2=1]=n;        for(i=n-1;i;i--)        {            while(top2>1&&xmul(p[stk2[top2-1]],p[stk2[top2]],p[i])>-eps)top2--;            stk2[++top2]=i;        }        n=0;        for(i=1;i<top1;i++)tp[++n]=p[stk1[i]];        for(i=1;i<top2;i++)tp[++n]=p[stk2[i]];        memcpy(p,tp,sizeof(Point)*(n+1));    }}qtb;int f[N][N];#define rig(x,y) ((x+y - 1)%n+1)#define lef(x,y) ((x-y+n-1)%n+1)inline double Area(int l,int r,int x){    double ret=xmul(Zero,p[l],p[r]);    ret+=xmul(Zero,p[r],p[x]);    ret+=xmul(Zero,p[x],p[l]);    return ret;}inline bool check(int l,int r,int a,int b){return Area(l,r,a)<Area(l,r,b);}int main(){    int i,j,k;    int a,b,c;    Zero=Point(0,0);    scanf("%d",&n);    for(i=1;i<=n;i++)p[i].read();    sort(p+1,p+n+1);    qtb.work();    for(i=1;i<=n;i++)    {        f[i][rig(i,2)]=rig(i,1);        for(j=rig(i,3);rig(j,1)!=i;j=rig(j,1))        {            f[i][j]=f[i][lef(j,1)];            while(rig(f[i][j],1)!=j&&                check(i,j,f[i][j],f[i][j]+1))f[i][j]++;        }    }    double ans=0.0;    for(i=1;i<=n;i++)for(j=rig(i,2);rig(j,1)!=i;j=rig(j,1))        ans=max(ans,Area(i,j,f[i][j])+Area(i,f[j][i],j));    printf("%.3lf\n",ans/2.0);    return 0;}
0 0