zoukankan      html  css  js  c++  java
  • Gym 101606B

    题目链接:https://codeforces.com/gym/101606/problem/B

    题解:

    对于给出的 $n$ 个点,先求这些点的凸包,然后用旋转卡壳求出凸包的宽度(Width (minimum width) of a convex polygon)即可。

    旋转卡壳求凸包的宽度和求凸包的直径(Diameter (maximum width) of a convex polygon)差不多。

    AC代码:

    #include<bits/stdc++.h>
    #define mk make_pair
    #define fi first
    #define se second
    #define pb push_back
    using namespace std;
    const double eps=1e-8;
    const double INF=1e18;
    
    int Sign(double x)
    {
        if(x<-eps) return -1;
        if(x>eps) return 1;
        return 0;
    }
    int Cmp(double x,double y){return Sign(x-y);}
    
    struct Point
    {
        double x,y;
        Point(double _x=0,double _y=0):x(_x),y(_y){}
        Point operator+(const Point &o)const{return Point(x+o.x,y+o.y);}
        Point operator-(const Point &o)const{return Point(x-o.x,y-o.y);}
        Point operator*(double k)const{return Point(x*k,y*k);}
        Point operator/(double k)const{return Point(x/k,y/k);}
        int operator==(const Point &o)const{return Cmp(x,o.x)==0 && Cmp(y,o.y)==0;}
        bool operator<(const Point &o)const
        {
            int sgn=Cmp(x,o.x);
            if(sgn==-1) return 1;
            else if(sgn==1) return 0;
            else return Cmp(y,o.y)==-1;
        }
        void print(){printf("%.11f %.11f
    ",x,y);}
    };
    typedef Point Vctor;
    
    //叉积
    double Cross(Vctor A,Vctor B){return A.x*B.y-A.y*B.x;}
    double Cross(Point O,Point A,Point B){return Cross(A-O,B-O);}
    
    //距离
    double Dot(Vctor A,Vctor B){return A.x*B.x+A.y*B.y;}
    double Length(Vctor A){return sqrt(Dot(A,A));}
    double Length(Point A,Point B){return Length(A-B);}
    
    vector<Point> ConvexHull(vector<Point> P,int flag=1) //flag=0不严格 flag=1严格
    {
        if(P.size()<=1) return P;
        int sz=P.size();
        vector<Point> ans(2*sz);
        sort(P.begin(),P.end());
        int now=-1;
        for(int i=0;i<sz;i++)
        {
            while(now>0 && Sign(Cross(ans[now]-ans[now-1],P[i]-ans[now-1]))<flag) now--;
            ans[++now]=P[i];
        }
        int pre=now;
        for(int i=sz-2;i>=0;i--)
        {
            while(now>pre && Sign(Cross(ans[now]-ans[now-1],P[i]-ans[now-1]))<flag) now--;
            ans[++now]=P[i];
        }
        ans.resize(now);
        return ans;
    }
    
    double RotatingCalipers(const vector<Point> &P) //旋转卡壳法
    {
        double ans=INF;
        int sz=P.size();
        for(int i=0,q=1;i<sz;i++)
        {
            int j=(i+1)%sz;
            while( Cross(P[j]-P[i],P[q]-P[i]) < Cross(P[j]-P[i],P[(q+1)%sz]-P[i]) ) q=(q+1)%sz;
            double d=fabs(Cross(P[i],P[j],P[q]))/Length(P[i],P[j]);
            ans=min(ans,d);
        }
        return ans;
    }
    
    int n;
    vector<Point> P;
    
    int main()
    {
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            double x,y; cin>>x>>y;
            P.pb(Point(x,y));
        }
        double ans=RotatingCalipers(ConvexHull(P));
        printf("%.8f
    ",ans);
    }
  • 相关阅读:
    Path类
    C#集合
    阿里巴巴2013年实习生笔试题B
    阿里巴巴2013年实习生笔试题A
    腾讯2014年校园招聘笔试试题
    腾讯技术类校园招聘笔试试题
    腾讯2013年实习生笔试题
    腾讯2012年实习生笔试题
    hdu1505
    hdu1506
  • 原文地址:https://www.cnblogs.com/dilthey/p/10720016.html
Copyright © 2011-2022 走看看