zoukankan      html  css  js  c++  java
  • Codeforces 605C Freelancer's Dreams 凸包 (看题解)

    Freelancer's Dreams

    我们把每个二元组看成是平面上的一个点, 那么两个点的线性组合是两点之间的连线, 即x * (a1, b1) + y * (a1, b1) && x + y == 1, 

    那么n个点的线性组合就是一个凸包, 那么我们求出凸包和(0, 0)到(p, q)直线的交的那个较大值就是最优的组合平均速度。

    需要注意的是, 直线和凸包可能没有交点, 需要加入(maxa, 0), (0, maxb)这两个点。

    #include<bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ull unsigned long long
    
    using namespace std;
    
    const int N = 2e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-8;
    const double PI = acos(-1);
    
    int dcmp(double x) {
        if(fabs(x) < eps) return 0;
        else return x < 0 ? -1 : 1;
    }
    
    struct Point {
        double x, y;
        Point(double x = 0, double y = 0) : x(x), y(y) {}
    };
    
    double dist(const Point& a, const Point& b) {
        return sqrt((a.x-b.x) * (a.x-b.x) + (a.y-b.y) * (a.y-b.y));
    }
    
    typedef Point Vector;
    
    Point operator + (Vector A, Vector B) {return Point(A.x + B.x, A.y + B.y);}
    Point operator - (Vector A, Vector B) {return Point(A.x - B.x, A.y - B.y);}
    Point operator * (Vector A, double p) {return Point(A.x * p, A.y * p);}
    Point operator / (Vector A, double p) {return Point(A.x / p, A.y / p);}
    bool operator < (const Vector &A, const Vector &B) {return A.x < B.x || (A.x == B.x && A.y < B.y);}
    bool operator == (const Vector &A, const Point &B) {return dcmp(A.x - B.x) == 0 && dcmp(A.y - B.y) == 0;}
    double Dot(Vector A, Vector B) {return A.x * B.x + A.y * B.y;}
    double Length(Vector A) {return sqrt(Dot(A, A));}
    double Angle(Vector A, Vector B) {return acos(Dot(A, B)/Length(A)/Length(B));}
    double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x;}
    double Area2(Point A, Point B, Point C) {return Cross(B-A, C-A);}
    
    bool IsPointOnSegment(const Point &p, const Point &a1, const Point &a2) {
        if(dcmp(Cross(a1-p,a2-p))) return 0;
        else if(dcmp(p.x-min(a1.x,a2.x)) >= 0 && dcmp(p.x-max(a1.x,a2.x)) <= 0
                && dcmp(p.y-min(a1.y,a2.y)) >= 0 && dcmp(p.y-max(a1.y,a2.y)) <= 0) return 1;
        else return 0;
    }
    
    Point GetLineIntersection(Point P, Vector v, Point Q, Vector w) {
        Vector u = P - Q;
        double t = Cross(w, u) / Cross(v, w);
        return P + v * t;
    }
    
    int ConvexHull(vector<Point>& p, vector<Point>& ch) {
        int n = p.size(), m = 0;
        sort(p.begin(), p.end());
        for(int i = 0; i < n; i++) {
            while(m > 1 && dcmp(Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])) <= 0) ch.pop_back(), m--;
            ch.push_back(p[i]); m++;
        }
        int k = m;
        for(int i = n - 2; i >= 0; i--) {
            while(m > k && dcmp(Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])) <= 0) ch.pop_back(), m--;
            ch.push_back(p[i]); m++;
        }
        return m;
    }
    
    int n, p, q;
    vector<Point> pt, ch;
    
    int main() {
        scanf("%d%d%d", &n, &p, &q);
        int mxa = -inf, mxb = -inf;
        for(int i = 1; i <= n; i++) {
            int a, b; scanf("%d%d", &a, &b);
            mxa = max(mxa, a);
            mxb = max(mxb, b);
            pt.push_back(Point(a, b));
        }
        pt.push_back(Point(mxa, 0));
        pt.push_back(Point(0, mxb));
        int m = ConvexHull(pt, ch);
        Point v = Point(p, q);
        Point ans = Point(-1, -1);
        for(int i = 0; i < m - 1; i++) {
            if(dcmp(Cross(ch[i], v)) * dcmp(Cross(v, ch[i + 1])) >= 0) {
                if(Cross(v, ch[i + 1] - ch[i]) == 0) continue;
                Point pp = GetLineIntersection(Point(0, 0), v, ch[i], ch[i + 1] - ch[i]);
                if(pp.x > ans.x) ans = pp;
            }
        }
        printf("%.12f
    ", v.x / ans.x);
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    LeetCode_145.二叉树的后序遍历
    LeetCode_144.二叉树的前序遍历
    LeetCode_142.环形链表 II
    LeetCode_141.环形链表
    LINQ查询表达式---------select子句
    LINQ查询表达式---------where子句
    LINQ查询表达式---------from子句
    System.InvalidOperationException: 未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序。
    Directory.GetFiles()获取多个类型格式的文件
    System.Exception: ORA-12541: TNS: 无监听程序
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10465578.html
Copyright © 2011-2022 走看看