zoukankan      html  css  js  c++  java
  • codeforces 606 E. Freelancer's Dreams(凸包)

    传送门:http://codeforces.com/contest/606/problem/E

    解题思路:

      我们可以将所有的$(a_{i},b_{i})$视为二维坐标轴上的点$(x,y)$,对于任意两点$(x_{1},y_{1}),(x_{2},y_{2})$,将这两点连起来,所形成的的线段上任意一点为一天的可以获得的量。

      那么当选取多个点时该如何考虑呢?假设有三个点A,B,C被选到,设D为BC上任意一点,ABC三点可以选取的点必然为AD上一点,不拿看出,这个范围是三角形ABC内部(含边界)。推广到n个点,单日可获得的必然是这n个点所构成的凸包。

      因此任务转化为了凸包内找一个点(x,y),使得$max(p/x,q/y)$最小。假设凸包和$(0,0)$到$(p,q)$的直线有交点,必然是取凸包和直线的交点,求出凸包,然后每一条线都check一下就好了,当然其实最多也只有两条线会相交。若无交点,而必然是凸包的顶点了,枚举一下即可。

      从得出的结论可以看出最多不会取超过两个点,因为必然是某一点,或者某两点连成的直线上的点,队友好像是根据这个性质用的三分做的。

      比赛的时候发现自己凸包的板子写的天花乱坠,既没有类封装,也没有函数封装,打了半天没打出来。

      最后贴上AC代码。

    #include<bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    typedef pair <double,double> pii;
    #define rep(i,x,y) for(int i=x;i<y;i++)
    #define rept(i,x,y) for(int i=x;i<=y;i++)
    #define per(i,x,y) for(int i=x;i>=y;i--)
    #define all(x) x.begin(),x.end()
    #define pb push_back
    #define fi first
    #define se second
    #define mes(a,b) memset(a,b,sizeof a)
    #define mp make_pair
    #define dd(x) cout<<#x<<"="<<x<<" "
    #define de(x) cout<<#x<<"="<<x<<"
    "
    #define debug() cout<<"I love Miyamizu Mitsuha forever.
    "
    const int inf=0x3f3f3f3f;
    const int maxn=1e5+5;
    pii p[maxn];
    
    
    pii point[maxn];//存放点
    double dis(const pii &s1,const pii &s2)//两点间距离
    {
        return sqrt((s1.fi-s2.fi)*(s1.fi-s2.fi)+(s1.se-s2.se)*(s1.se-s2.se));
    }
    pii operator -(const pii &s1,const pii &s2)
    {
        return mp(s1.fi-s2.fi,s1.se-s2.se);
    }
    double chaji(const pii &s1,const pii &s2)//差积 
    {
        return s1.fi*s2.se-s1.se*s2.fi;
    }
    bool comp(const pii &s1,const pii &s2)
    {
        double x=chaji(s1-point[0],s2-point[0]);
        if( x>0|| (x==0&&fabs(s1.fi-point[0].fi)<fabs(s2.fi-point[0].fi)) ) return 1;
        else return 0;
    }
    
    int graham(pii point[],int n)//计算凸包
    {
        int p=0,cnt=0;
        rep(i,1,n)
            if( point[i].se<point[p].se||(point[i].se==point[p].se&&point[i].fi<point[p].fi) )
                p=i;
        swap(point[0],point[p]);
        sort(point+1,point+n,comp);
        cnt=2;
        rep(i,2,n)
        {
            while(cnt>=2&&chaji( point[cnt-1]-point[i],point[cnt-2]-point[i] )>=0 ) cnt--;
            point[cnt++]=point[i];
        }
        return cnt;
    }
    
    double a,b;
    pii node(pii s1,pii s2)
    {
        double x=( (s1.se*s2.fi-s1.fi*s2.se)/(s2.fi-s1.fi) )/(b/a-(s2.se-s1.se)/(s2.fi-s1.fi));
        double y=b/a*x;
        return mp(x,y);
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n;
        cin>>n>>a>>b;
        rep(i,0,n) cin>>p[i].fi>>p[i].se;
        if(n==1)
        {
            cout<<fixed<<setprecision(10)<<max(a/p[0].fi,b/p[0].se);
            return 0;
        }
        int cnt=graham(p,n);
        double ans=1e18;
        rep(i,0,cnt-1)
        {
            pii point=node(p[i],p[i+1]);//求交点
            if(point.fi<=p[i].fi&&point.fi>=p[i+1].fi) ans=min(ans,a/point.fi);//判断交点是否在线段上
        }
        rep(i,0,cnt) ans=min(ans,max(a/p[i].fi,b/p[i].se));
        cout<<fixed<<setprecision(10)<<ans<<"
    ";
        return 0;
    }
  • 相关阅读:
    NYOJ 625 笨蛋的难题(二)
    NYOJ 102 次方求模
    ZJU Least Common Multiple
    ZJUOJ 1073 Round and Round We Go
    NYOJ 709 异形卵
    HDU 1279 验证角谷猜想
    BNUOJ 1015 信息战(一)——加密程序
    HDU 1202 The calculation of GPA
    "蓝桥杯“基础练习:字母图形
    "蓝桥杯“基础练习:数列特征
  • 原文地址:https://www.cnblogs.com/FZUzyz/p/12847029.html
Copyright © 2011-2022 走看看