p278.cpp
======================
#include <bits/stdc++.h>
// #include <coding_library/geometry/geometry2d.hpp>

using namespace std;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, const pair<T1, T2>& x) {
    return out << x.first << ' ' << x.second;
}

template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& x) {
    return in >> x.first >> x.second;
}

template<typename T>
istream& operator>>(istream& in, vector<T>& a) {
    for(auto& x: a) {
        in >> x;
    }
    return in;
};

template<typename T>
ostream& operator<<(ostream& out, const vector<T>& a) {
    for(auto x: a) {
        out << x << ' ';
    }
    return out;
};

using coord_t = long double;

struct Point {
    static constexpr coord_t eps = 1e-9;

    coord_t x, y;
    Point(coord_t x = 0, coord_t y = 0) : x(x), y(y) {}

    Point operator+(const Point& p) const { return Point(x + p.x, y + p.y); }
    Point operator-(const Point& p) const { return Point(x - p.x, y - p.y); }
    Point operator*(coord_t c) const { return Point(x * c, y * c); }
    Point operator/(coord_t c) const { return Point(x / c, y / c); }

    coord_t operator*(const Point& p) const { return x * p.x + y * p.y; }
    coord_t operator^(const Point& p) const { return x * p.y - y * p.x; }

    bool operator==(const Point& p) const { return x == p.x && y == p.y; }
    bool operator!=(const Point& p) const { return x != p.x || y != p.y; }
    bool operator<(const Point& p) const {
        return x != p.x ? x < p.x : y < p.y;
    }
    bool operator>(const Point& p) const {
        return x != p.x ? x > p.x : y > p.y;
    }
    bool operator<=(const Point& p) const {
        return x != p.x ? x < p.x : y <= p.y;
    }
    bool operator>=(const Point& p) const {
        return x != p.x ? x > p.x : y >= p.y;
    }

    coord_t norm2() const { return x * x + y * y; }
    double norm() const { return sqrt(norm2()); }
    double angle() const { return atan2(y, x); }

    Point rotate(double a) const {
        return Point(x * cos(a) - y * sin(a), x * sin(a) + y * cos(a));
    }

    Point perp() const { return Point(-y, x); }
    Point unit() const { return *this / norm(); }
    Point normal() const { return perp().unit(); }
    Point project(const Point& p) const {
        return *this * (*this * p) / norm2();
    }
    Point reflect(const Point& p) const {
        return *this * 2 * (*this * p) / norm2() - p;
    }

    friend ostream& operator<<(ostream& os, const Point& p) {
        return os << p.x << ' ' << p.y;
    }
    friend istream& operator>>(istream& is, Point& p) {
        return is >> p.x >> p.y;
    }

    friend int ccw(const Point& a, const Point& b, const Point& c) {
        coord_t v = (b - a) ^ (c - a);
        if(-eps <= v && v <= eps) {
            return 0;
        } else if(v > 0) {
            return 1;
        } else {
            return -1;
        }
    }

    friend bool point_on_segment(
        const Point& a, const Point& b, const Point& p
    ) {
        return ccw(a, b, p) == 0 && p.x >= min(a.x, b.x) - eps &&
               p.x <= max(a.x, b.x) + eps && p.y >= min(a.y, b.y) - eps &&
               p.y <= max(a.y, b.y) + eps;
    }

    friend bool point_in_triangle(
        const Point& a, const Point& b, const Point& c, const Point& p
    ) {
        int d1 = ccw(a, b, p);
        int d2 = ccw(b, c, p);
        int d3 = ccw(c, a, p);
        return (d1 >= 0 && d2 >= 0 && d3 >= 0) ||
               (d1 <= 0 && d2 <= 0 && d3 <= 0);
    }

    friend Point line_line_intersection(
        const Point& a1, const Point& b1, const Point& a2, const Point& b2
    ) {
        return a1 +
               (b1 - a1) * ((a2 - a1) ^ (b2 - a2)) / ((b1 - a1) ^ (b2 - a2));
    }
};

class Polygon {
  public:
    vector<Point> points;

    Polygon() {}
    Polygon(const vector<Point>& points) : points(points) {}

    int size() const { return points.size(); }

    coord_t area() const {
        coord_t a = 0;
        for(int i = 0; i < size(); i++) {
            a += points[i] ^ points[(i + 1) % size()];
        }
        return a / 2.0;
    }
};

class ConvexHull : public Polygon {
  public:
    int upper_hull_size;

    ConvexHull(const vector<Point>& points) {
        this->points = points;
        sort(this->points.begin(), this->points.end());
        this->points.erase(
            unique(this->points.begin(), this->points.end()), this->points.end()
        );

        if(this->points.size() <= 2) {
            this->upper_hull_size = this->points.size();
            return;
        }

        vector<int> hull = {0};
        vector<bool> used(this->points.size());

        function<void(int, int)> expand_hull = [&](int i, int min_hull_size) {
            while((int)hull.size() >= min_hull_size &&
                  ccw(this->points[hull[hull.size() - 2]],
                      this->points[hull.back()], this->points[i]) >= 0) {
                used[hull.back()] = false;
                hull.pop_back();
            }
            hull.push_back(i);
            used[i] = true;
        };

        for(int i = 1; i < (int)this->points.size(); i++) {
            expand_hull(i, 2);
        }

        upper_hull_size = hull.size();
        for(int i = (int)this->points.size() - 2; i >= 0; i--) {
            if(!used[i]) {
                expand_hull(i, upper_hull_size + 1);
            }
        }

        hull.pop_back();

        vector<Point> points_in_hull;
        for(int i: hull) {
            points_in_hull.push_back(this->points[i]);
        }
        this->points = std::move(points_in_hull);
    }
};

int n;
coord_t A, B;
vector<tuple<int, int, int>> fuels;

void read() {
    cin >> n >> A >> B;
    fuels.resize(n);
    for(auto& [x, y, z]: fuels) {
        cin >> x >> y >> z;
    }
}

void solve() {
    coord_t ans = 0.0;
    vector<Point> points;
    for(int i = 0; i < n; i++) {
        points.push_back(Point(
            get<0>(fuels[i]) / (coord_t)get<2>(fuels[i]),
            get<1>(fuels[i]) / (coord_t)get<2>(fuels[i])
        ));
        ans = max(ans, min(A / points[i].x, B / points[i].y));
    }

    ConvexHull hull(points);

    Point origin(0, 0), target_loc(A, B);
    for(int i = 0; i < (int)hull.points.size(); i++) {
        Point p1 = hull.points[i];
        Point p2 = hull.points[(i + 1) % hull.points.size()];

        if(fabs((target_loc - origin) ^ (p1 - p2)) > Point::eps) {
            Point intersection =
                line_line_intersection(origin, target_loc, p1, p2);
            if(point_on_segment(p1, p2, intersection)) {
                ans = max(ans, min(A / intersection.x, B / intersection.y));
            }
        }
    }

    cout << setprecision(6) << fixed << ans << fixed;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int T = 1;
    // cin >> T;
    for(int test = 1; test <= T; test++) {
        read();
        // cout << "Case #" << test << ": ";
        solve();
    }

    return 0;
}

=================
p278.ans1
======================
4.000000

=================
p278.in1
======================
2 1 1 
1 2 6
2 1 6

=================
p278.ans2
======================
0.0

=================
statement.txt
======================
278. Fuel
Time limit per test: 0.5 second(s)
Memory limit: 65536 kilobytes
input: standard
output: standard



A fuel station has infinite amount of each of N kinds of fuel. Each kind of fuel has density ai, cost bi and intensity ci. m kilograms of such fuel has volume mai, intensity mci and costs mbi dollars. Your car can store any mixture of different kinds of fuel such that the overall volume does not exceed A. You have B dollars. Your task is to determine the maximal overall intensity of the fuel you can buy. Note that you can buy any nonnegative amount of any kind of fuel, not necessarily an integer number of kilograms.

Input
The first line of the input contains three integers N, A, B (1≤ N≤ 75000, 1≤ A,B≤ 1000). Each of the next N lines describes one kind of fuel. i+1-st line contains three integers ai, bi, ci (0i,bi,ci≤ 100).

Output
The only line of the output must contain single number with at least 6 digits after the decimal point, being the maximal overall intensity.

Example(s)
sample input
sample output
2 1 1 
1 2 6
2 1 6
4.000000



Novosibirsk SU Contest #2, by Novosibirsk Team #1

=================
p278.in2
======================
5 1 1
1 5 1
2 4 1
3 6 1
4 4 1
5 5 1

=================
