zoukankan      html  css  js  c++  java
  • UVALive 4728 Squares (平面最远点对)

    题意:n个平行于坐标轴的正方形,求出最远点对的平方

    题解:首先求出凸包,可以证明最远点对一定是凸包上的点对,接着可以证明最远点对(每个点的对踵点)一定只有3*n/2对

    接着使用旋转卡壳找到最远点对,但是白书上的算法过于麻烦

    所以我看到一个简单想法就是:

    可以直接枚举每个点,接着枚举这个点对应最远的点(三角形面积最大)

    这儿对踵点满足一个单峰性质,所以可以使用类似双指针方式维护

    //n个平行于坐标轴的正方形,求出最远点对的平方
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    #define eps 1e-8
    #define sgn(x) (x<-eps? -1 : x<eps? 0:1)
    #define zero(x) (((x)>0?(x) : -(x))<eps)
    const int Max=5e5+7;
    struct Point
    {
        double x,y;
        Point(double x=0,double y=0):x(x),y(y) {}
        inline Point operator-(const Point& a)const
        {
            return Point(x-a.x,y-a.y);
        }
        inline bool operator<(const Point& a)const
        {
            return sgn(x-a.x)<0||zero(x-a.x)&&sgn(y-a.y)<0;
        }
        inline bool operator!=(const Point& a)const
        {
            return !(zero(x-a.x)&&zero(y-a.y));
        }
    };
    typedef Point Vector;
    double Cross(Vector A,Vector B)
    {
        return A.x*B.y-A.y*B.x;
    }
    double Dis(Point A,Point B)
    {
        return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
    }
    int ConvexHull(Point* p,int n,Point* convex)
    {
        sort(p,p+n);
        int m=0,k=1;
        for(int i=0; i<n; ++i)
        {
            if(p[k-1]!=p[i])
            {
                p[k++]=p[i];
            }
        }
        n=k;
        for(int i=0; i<n; ++i)
        {
            while(m>1&&Cross(convex[m-1]-convex[m-2],p[i]-convex[m-2])<0)
                m--;
            convex[m++]=p[i];
        }
        k=m;
        for(int i=n-2; i>=0; --i)
        {
            while(m>k&&Cross(convex[m-1]-convex[m-2],p[i]-convex[m-2])<0)
                m--;
            convex[m++]=p[i];
        }
        if(n>1)
            m--;
        return m;
    }
    double RotateStuck(Point* convex,int n)//旋转卡壳(前提:一个凸包),注意凸包去重点不要三点共线
    {
        double ans=0;
        int q=1;
        convex[n]=convex[0];//避免取模
        for(int p=0; p<n; ++p)//枚举一条边
        {
            while(Cross(convex[p+1]-convex[p],convex[q+1]-convex[p])>//这儿用的是三角形面积的比较
                  Cross(convex[p+1]-convex[p],convex[q]-convex[p]))//找到对应p这条个点的最远点(由于单峰函数,所以结果类似双指针)
                q=(q+1)%n;
            ans=max(ans,max(Dis(convex[p],convex[q]),Dis(convex[p+1],convex[q+1])));
        }
        return ans;
    }
    Point poi[Max],convex[Max];
    double Solve(int n)//求出最远点对的平方
    {
        double fpp=0;
        int m=ConvexHull(poi,n,convex);//先找凸包
        fpp=RotateStuck(convex,m);//旋转卡壳求对踵点(可以求出凸包上的最远点对)
        return fpp*fpp;
    }
    int main()
    {
        int t,n;
        double w,x,y;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            for(int i=0; i<n; ++i)
            {
                scanf("%lf%lf%lf",&x,&y,&w);
                poi[4*i]=Point(x,y);
                poi[4*i+1]=Point(x+w,y);
                poi[4*i+2]=Point(x,y+w);
                poi[4*i+3]=Point(x+w,y+w);
            }
            printf("%.0f
    ",Solve(4*n));
        }
        return 0;
    }
  • 相关阅读:
    [BOST] 博赞有机的学习技巧
    [BOST] 你的大脑比你想象的更优秀
    Markdown学习笔记
    nodejs原生态模块,写个聊天室
    【2】自定义WindowsForm分页控件使用【共两篇】
    【1】自定义WindowsForm分页控件使用【共两篇】
    《Log4net写出适合自己的日志类》第三篇【终】【怎样让它适合你自己需求】
    《Log4net写出适合自己的日志类》第二篇【没有理论的实践是盲目】
    《Log4net写出适合自己的日志类》第一篇【上来就是干,先实践后理论】
    记忆留住深刻过往,博客写出平淡事迹【博客首篇】
  • 原文地址:https://www.cnblogs.com/zhuanzhuruyi/p/6234841.html
Copyright © 2011-2022 走看看