中国石油大学开放训练赛 B.奎奎发红包(贪心)

贪心(根据数学表达式确定贪心方法)

奎奎发红包

  • 题目

    奎奎给n个人发红包,每个人都两个值v[i]t[i]t[i]代表给第i个人发红包所需的时间。
    每个人的红包大小为v[i]*tt表示这个人的等待时间(包括自己所需时间)。
    问最少花多少钱能满足每一个人?

  • 输入

    4
    1 4
    2 3
    3 2
    4 1
    
  • 输出

    35
    

考虑相邻的两个人a,b,如果a排在前面,代价为 a . v ∗ a . t + b . v ∗ ( a . t + b . t ) a.v*a.t+b.v*(a.t+b.t) a.va.t+b.v(a.t+b.t);如果b排在前面,代价为 b . v ∗ b . t + a . v ∗ ( a . t + b . t ) b.v*b.t+a.v*(a.t+b.t) b.vb.t+a.v(a.t+b.t)。对两式进行化简得:如果 a . t ∗ b . v < a . v ∗ b . t a.t*b.v<a.v*b.t a.tb.v<a.vb.t,则a应该排在前面,也就是 a . t a . v < b . t b . v \frac{a.t}{a.v}<\frac{b.t}{b.v} a.va.t<b.vb.t
所以按照 t v \frac{t}{v} vt的排序,但需要特别考虑0的情况,因为v=0时不用花钱,所以可以放到最后不管。

#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
#define endl '\n'
typedef long long ll;
const int maxn = 1e5 + 10;
struct node {
    int v, t;
    bool operator<(const node b) const
    {
        return 1.0 * this->t / this->v < 1.0 * b.t / b.v;
    }
} a[maxn];
int n, t, v, num;
bool cmp(node a, node b)
{
    return 1.0 * a.t / a.v < 1.0 * b.t / b.v;
}
int main()
{
    ios::sync_with_stdio(0), cin.tie(0);
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> v >> t;
        if (v != 0) {
            a[i].v = v;
            a[i].t = t;
            num++;
        }
    }
    sort(a + 1, a + 1 + num);
    ll ans = 0, sum = 0;
    for (int i = 1; i <= num; i++) {
        sum += a[i].t;
        ans += a[i].v * sum;
    }
    cout << ans << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值