zoukankan      html  css  js  c++  java
  • bzoj1069 [SCOI2007]最大土地面积

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

    Input
      第1行一个正整数N,接下来N行,每行2个数x,y,表示该点的横坐标和纵坐标。

    Output
      最大的多边形面积,答案精确到小数点后3位。

    Sample Input
    5
    0 0
    1 0
    1 1
    0 1
    0.5 0.5

    Sample Output
    1.000

    HINT
    数据范围 n<=2000, |x|,|y|<=100000

    分析:
    明确我们要找的点一定在凸包上,
    二话不说先来一个凸包

    注意:凸包的板子不要打错了

    这样我们在凸包上就可以卡壳了

    我们枚举四边形的对角线,在四边形的两侧找到距离对角线最远的两个点
    计算这样的四边形的面积,取max
    因为距离最远的点也是单调的,所以时间O(n^2)

    tip

    很奇怪我第一次T了

    看一下怎么找距离最远的点吧

    double k=fabs(Cross(po[sta[p2]]-po[sta[i]],po[sta[p1+1]]-po[sta[i]]))
            -fabs(Cross(po[sta[p2]]-po[sta[i]],po[sta[p1]]-po[sta[i]]));
    if (dcmp(k)<=0) break;
    else p1++;   //p1+1离ip2更远

    k是i和p2(对角线)分别和p1+1,p1构成的三角形的面积差
    如果k>0说明p1距离对角线更远

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    
    using namespace std;
    
    const double INF=1e10;
    const double eps=1e-10;
    const int N=2010;
    struct node{
        double x,y;
        node (double xx=0,double yy=0)
        {
            x=xx;y=yy;
        }
    };
    node po[N];
    int n,sta[N],top;
    
    int dcmp(double x)
    {
        if (fabs(x)<eps) return 0;
        else if (x>0) return 1;
        else return -1;
    }
    
    int cmp(const node &a,const node &b)
    {
        if (dcmp(a.x-b.x)!=0) return a.x<b.x;
        else return a.y<b.y;
    }
    
    node operator +(const node &a,const node &b){return node(a.x+b.x,a.y+b.y);}
    node operator -(const node &a,const node &b){return node(a.x-b.x,a.y-b.y);}
    node operator *(const node &a,const double &b){return node(a.x*b,a.y*b);}
    node operator /(const node &a,const double &b){return node(a.x/b,a.y/b);}
    bool operator ==(const node &a,const node &b){
        return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
    }
    
    double mx(double a,double b)
    {
        if (dcmp(a-b)>0) return a;
        else return b;
    }
    
    double Cross(node x,node y){return x.x*y.y-x.y*y.x;}
    double Dot(node x,node y){return x.x*y.x+x.y*y.y;}
    
    void TuB()
    {
        int i;
        top=0;
        sort(po+1,po+1+n,cmp);
        for (i=1;i<=n;i++)
        {
            while (top>1&&dcmp(Cross(po[i]-po[sta[top-1]],po[sta[top]]-po[sta[top-1]]))<=0) top--;
            sta[++top]=i;
        }
        int k=top;
        for (i=n-1;i>=1;i--)
        {
            while (top>k&&dcmp(Cross(po[i]-po[sta[top-1]],po[sta[top]]-po[sta[top-1]]))<=0) top--;
            sta[++top]=i;
        }
        if (n>1) top--;
    }
    
    double len(node a,node b,node p)
    {
        return fabs(Cross(p-a,b-a))/sqrt(Dot(a-b,a-b));
    }
    
    double SS(node a,node b,node c,node d)
    {
        double f1=Cross(b-a,c-a);
        double f2=Cross(c-a,d-a);
        double r=fabs(Cross(b-a,c-a)+Cross(c-a,d-a))/2;
        return fabs(Cross(b-a,c-a)+Cross(c-a,d-a))/2;
    }
    
    void solve()
    {
        int i,j;
        double ans=0;
        for (i=1;i<=top;i++) sta[top+i]=sta[i];  //变成环 
        for (i=1;i<top;i++)
        {
            int p1=i+1;
            int p2=p1+1;  //对角线 
            int p3=p2+1;
            for (;p2<top+i-1;p2++)
            {
                while (1)
                {
                    double k=fabs(Cross(po[sta[p2]]-po[sta[i]],po[sta[p1+1]]-po[sta[i]]))
                    -fabs(Cross(po[sta[p2]]-po[sta[i]],po[sta[p1]]-po[sta[i]]));
                    if (dcmp(k)<=0) break;
                    else p1++;   //p1+1离ip2更远 
                }
                while (1)
                {
                    double k=fabs(Cross(po[sta[p2]]-po[sta[i]],po[sta[p3+1]]-po[sta[i]]))
                    -fabs(Cross(po[sta[p2]]-po[sta[i]],po[sta[p3]]-po[sta[i]]));
                    if (dcmp(k)<=0) break;
                    else p3++;   //p3+1离ip2更远 
                }
                //if (p3>=top+i) break;  //转了超过一圈 
                ans=mx(ans,SS(po[sta[i]],po[sta[p1]],po[sta[p2]],po[sta[p3]]));  //顺时针 
            } 
        }
        printf("%0.3lf",ans);
    }
    
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++) 
        scanf("%lf%lf",&po[i].x,&po[i].y);
        TuB();
        solve();
        return 0;
    }
  • 相关阅读:
    Linux学习笔记21——线程同步的两种方式
    Linux学习笔记20——第一个多线程程序
    Linux学习笔记19——信号2
    Linux学习笔记18——信号1
    Linux学习笔记17——输入输出重定向
    Linux学习笔记16——wait函数
    Linux学习笔记15——GDB 命令详细解释【转】
    Linux学习笔记14——使用fcntl实现文件锁定
    Linux学习笔记13——使用curses函数库
    Linux学习笔记12——Unix中的进程
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673427.html
Copyright © 2011-2022 走看看