SGU 278|Fuel|凸包

有N种汽油每种有三个属性:密度 ai ,强度 ci ,价格 bi 。用第i种汽油 m kg拥有mai的体积,m*ci_的强度,花费 mbi 。汽车能装任意比例混合的多种汽油。总体积不能超过 A ,总花费不能超过B,最大化总强度,保留至少6位小数。

miaiAmibiBmaxmici

一看数据范围。。单纯形boom。。
好了我们重新考虑一下吧。。

如果我们令

di=aici,ei=bici,xi=cimi
那么
dixiAeixiBmaxxi

#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 75000;
struct Point {
    double x, y;
    Point(double _x = 0, double _y = 0) : x(_x), y(_y) { }
    Point operator/ (double b) const { return Point(x / b, y / b); }
};
int q[N], a[N], b[N], c[N], o[N];
Point intersection(int u, int v) {
    double det = a[u] * b[v] - a[v] * b[u];
    return Point(b[v] * c[u] - b[u] * c[v], a[u] * c[v] - a[v] * c[u]) / det;
}
bool is_convex(int u, int v, int w) {
    Point p = intersection(v, w);
    return a[u] * p.x + b[u] * p.y > c[u];
}
int main() {
    int i, x, y, A, B, n;
    scanf("%d%d%d", &n, &A, &B);
    for (i = 0; i < n; ++i) {
        scanf("%d%d%d", a + i, b + i, c + i);
        o[i] = i;
    }
    sort(o, o + n, [](int i,int j){return a[i] * b[j] - a[j] * b[i] > 0;});
    int f = 0, r = 0;
    for (i = 0; i < n; ++i) {
        x = o[i];
        if (f < r) {
            y = q[r - 1];
            if (a[x] * b[y] == a[y] * b[x]) {
                if (c[y] / b[y] >= c[x] / b[x]) continue;
                --r;
            }
        }
        while (r - f >= 2 && !is_convex(q[r - 2], q[r - 1], x)) --r;
        q[r++] = x;
    }
    for (; r - f >= 2; ++f)
        if (intersection(q[f], q[f + 1]).x >= 0) break;
    for (; r - f >= 2; --r)
        if (intersection(q[r - 2], q[r - 1]).y >= 0) break;
    double ans = min(1.0 * B * c[q[f]] / b[q[f]], 1.0 * A * c[q[r - 1]] / a[q[r - 1]]);
    for (i = f + 1; i < r; ++i) {
        Point p = intersection(q[i - 1], q[i]);
        ans = min(ans, A * max(p.x, 0.0) + B * max(p.y, 0.0));
    }
    printf("%.6f\n", ans);
    return 0;
}

Fuel

Time Limit: 500MS

Description

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 (0 i, 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.

Sample Input

2 1 1
1 2 6
2 1 6

Sample Output

4.000000
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct Point {
    double x, y;
    Point() { }
    Point(double _x, double _y) : x(_x), y(_y) { }
    Point operator+ (const Point &b) const { return Point(x + b.x, y + b.y); }
    Point operator- (const Point &b) const { return Point(x - b.x, y - b.y); }
    double operator* (const Point &b) const { return x * b.y - y * b.x; }
    Point operator* (double b) const { return Point(x * b, y * b); }
    Point operator/ (double b) const { return Point(x / b, y / b); }
};
const int N = 75000;
int n, d, e, q[N], a[N], b[N], c[N], order[N];
bool cmp(int i, int j) {
    return a[i] * b[j] - a[j] * b[i] > 0;
}
double dist(int u) {
    return c[u] / sqrt(a[u] * a[u] + b[u] * b[u]);
}
Point intersection(int u, int v) {
    double det = a[u] * b[v] - a[v] * b[u];
    return Point(b[v] * c[u] - b[u] * c[v], a[u] * c[v] - a[v] * c[u]) / det;
}
bool is_convex(int u, int v, int w) {
    Point p = intersection(v, w);
    return a[u] * p.x + b[u] * p.y > c[u];
}
int main() {
    int i, u, v;
    scanf("%d%d%d", &n, &d, &e);
    for (i = 0; i < n; ++i) {
        scanf("%d%d%d", a + i, b + i, c + i);
        order[i] = i;
    }
    sort(order, order + n, cmp);
    int f = 0, r = 0;
    for (i = 0; i < n; ++ i) {
        u = order[i];
        if (f < r) {
            v = q[r - 1];
            if (!cmp(u, v) && !cmp(v, u)) {
                if (dist(v) >= dist(u)) continue;
                --r;
            }
        }
        while (r - f >= 2 && !is_convex(q[r - 2], q[r - 1], u)) --r;
        q[r++] = u;
    }
    while (r - f >= 2) {
        Point p = intersection(q[f], q[f + 1]);
        if (p.x >= 0) break;
        ++f;
    }
    while (r - f >= 2) {
        Point p = intersection(q[r - 2], q[r - 1]);
        if (p.y >= 0) break;
        --r;
    }
    double ans = min(1. * e * c[q[f]] / b[q[f]], 1. * d * c[q[r - 1]] / a[q[f - 1]]);
    for (i = f + 1; i < r; ++i) {
        Point p = intersection(q[i - 1], q[i]);
        ans = min(ans, d * max(p.x, 0.0) + e * max(p.y, 0.0));
    }
    printf("%.6f\n", ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值