首先最任务进行排序,首先按截止时间进行排序然后按z的值从大到小进行排序。按截止时间进行排序是因为如果过了截止时间那就相当于没完成,所以比较优先,那之后为什么按照z的值进行排序呢?因为z的值大能耗费更小的钱去买。在做任务的过程中如果前面任务的时间相加超过当前任务的截止时间了,就得需要向前面的任务以及他自身要时间,这时候自然要选取运行时间不为0且z值最大的那一个。那么可以使用一个优先队列来维护z值的大根堆,如果因为花钱导致运行时间为0了就从堆里面剔除就好了。
#include <bits/stdc++.h>


using namespace std;
// #define int double;
struct Node {
    double z, x, y;
    Node(double Z, double X, double Y) {
        z = Z;
        x = X;
        y = Y;
    }
};

struct ncomp {
    bool operator () (const Node &n1, const Node &n2) const
    {
        return n1.z<n2.z;
    }
};

int n;
vector<Node> vt;
priority_queue<Node, vector<Node>, ncomp> pq;
bool comp(Node n1, Node n2) {
    if (n1.y==n2.y) return n1.z>n2.z;
    return n1.y<n2.y;
}

signed main() {
    cin>>n;
    int z, x, y;
    for (int i=0;i<n;i++) {
        cin>>z>>x>>y;
        Node nd(z,x,y);
        vt.push_back(nd);
    }
    sort(vt.begin(), vt.end(), comp);
    double num = 0;
    double ans = 0;
    for (int i=0;i<n;i++) {
        Node node = vt[i];
        //将这个任务加入优先队列
        pq.push(node);
        num += node.x;
        //如果超时了
        if (num>node.y) {
            //计算超时多少
            double cha = num-node.y;
            //从优先队列里面取出z最大的那一个  
            Node nd = pq.top();
            pq.pop();
            while (cha!=0) {
                if (nd.x>cha) {
                    ans += 1.0*cha/nd.z;
                    nd.x -= cha;
                    cha = 0;
                    pq.push(nd);
                } else {
                    ans += 1.0*nd.x/nd.z;
                    cha -= nd.x;
                    if (cha!=0) {
                        nd = pq.top();
                        pq.pop();
                    }
                }
            }
            num = node.y;
        }
    }
    printf("%.1f\n", round(ans*10)/10.0);
    return 0;
}