我们把每个二元组看成是平面上的一个点, 那么两个点的线性组合是两点之间的连线, 即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\n", v.x / ans.x); return 0; } /* */
Codeforces 605C Freelancer's Dreams 凸包
原文地址:https://www.cnblogs.com/CJLHY/p/10465578.html
时间: 2024-10-08 18:03:41