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

    题目:BZOJ1069、洛谷P4166。

    题目大意:

    平面上给定n个点,让你选4个点,使得其围成的多边形面积最大。求这个面积。

    解题思路:

    首先显然的,要使面积最大,则点肯定在凸包上。

    然后,由于数据较小(nleqslant 1500),我们枚举四边形对角线的两个点,然后相当于在对角线两侧分别找1个点使得三个点围成的三角形面积最大。

    旋转卡壳。

    C++ Code:

    #include<bits/stdc++.h>
    int n;
    struct point{
        double x,y,deg;
        inline point operator+(const point&rhs){return(point){x+rhs.x,y+rhs.y,0};};
        inline point operator-(const point&rhs){return(point){x-rhs.x,y-rhs.y,0};};
        inline bool operator<(const point&rhs)const{return deg+1e-15<rhs.deg;}
    }a[2333];
    std::vector<point>v;
    inline double cross(point a,point b){
        return a.x*b.y-a.y*b.x;
    }
    double anss[2021][2021];
    void graham(point*a,int n){
        a[++n]=a[1];
        v.push_back(a[1]);
        v.push_back(a[2]);
        for(int i=3;i<=n;++i){
            while(v.size()>1&&cross(v.back()-v[v.size()-2],a[i]-v[v.size()-2])<=0)v.pop_back();
            v.push_back(a[i]);
        }
    }
    int main(){
        scanf("%d",&n);
        int down=1; 
        for(int i=1;i<=n;++i){
            scanf("%lf%lf",&a[i].x,&a[i].y);
            if(a[i].y<a[down].y||a[i].y==a[down].y&&a[i].x<a[down].x)down=i;
        }
        std::swap(a[1],a[down]);
        for(int i=2;i<=n;++i)a[i]=a[i]-a[1];
        a[1]=(point){0,0};
        for(int i=2;i<=n;++i)a[i].deg=atan2(a[i].y,a[i].x);
        std::sort(a+2,a+n+1);
        graham(a,n);
        v.pop_back();
        int sz=v.size();
        for(int i=0;i<sz;++i)v.push_back(v[i]);
    //  for(auto i:v)printf("%.2f %.2f ,",i.x,i.y);
    //  puts("");
        double ans=0;
        for(int i=0;i<sz;++i){
            int np=i+1;
            for(int j=i+2;j<sz;++j){
                while(np+1<j&&cross(v[np]-v[i],v[j]-v[i])<cross(v[np+1]-v[i],v[j]-v[i])+1e-15)++np;
                anss[i][j]=cross(v[np]-v[i],v[j]-v[i]);
            }
        }
        for(int i=sz-1;~i;--i){
            int np=i+1;
            for(int jj=0;jj+1<i;++jj){
                const int j=jj+sz;
                while(np+1<j&&cross(v[np]-v[i],v[j]-v[i])<cross(v[np+1]-v[i],v[j]-v[i])+1e-15)++np;
                anss[jj][i]+=cross(v[np]-v[i],v[j]-v[i]);
                if(anss[jj][i]>ans)ans=anss[jj][i];
            }
        }
        printf("%.3f
    ",ans/2);
        return 0;
    }
  • 相关阅读:
    【转】如何删除一个repository(仓库)
    【转】Android将Activity打成jar包供第三方调用(解决资源文件不能打包的问题)
    【转】android 开发 命名规范
    【转】精简深拷贝ArrayList实例
    【转】关于Adapter的The content of the adapter has changed问题分析 关于Adapter的The content of the adapter has changed问题分析
    从 BM 到 RBM
    从 BM 到 RBM
    Gibbs 采样的应用
    Gibbs 采样的应用
    MCMC:Gibbs 采样(matlab 实现)
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9343812.html
Copyright © 2011-2022 走看看