题目链接:点击打开链接
思路:一开始一直在想, 对于当前的一个任务i,他到底应该花费多少合适, 因为会影响后面的决策。 后来才想明白一件事, 对于当前这个任务, 减少他的时间和减少之前任意一个任务的时间是等价的, 那么我们当然优先减少那些a比较大的。 如果当前这个任务无法完成, 那么就在之前的所有任务中找a尽量大的来减少时间。 显然, 是一定有解的。
细节参见代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <string> #include <vector> #include <stack> #include <bitset> #include <cstdlib> #include <cmath> #include <set> #include <list> #include <deque> #include <map> #include <queue> #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) using namespace std; typedef long long ll; typedef long double ld; const double eps = 1e-3; const double PI = acos(-1); const int mod = 1000000000 + 7; const int INF = 0x3f3f3f3f; const int seed = 131; const ll INF64 = ll(1e18); const int maxn = 1e5 + 10; int T,n,m; struct node { double a, b, cost; node(double a=0, double b=0, double cost=0) : a(a), b(b), cost(cost) {} bool operator < (const node& rhs) const { return a < rhs.a; } }; struct edge { double a, b, d; bool operator < (const edge& rhs) const { return d < rhs.d; } }a[maxn]; inline bool eqdown(double a, double b) { if(a < b || fabs(a - b) < eps) return true; else return false; } double solve() { priority_queue<node> q; double time = 0, ans = 0; for(int i = 0; i < n; i++) { q.push(node(a[i].a, a[i].b, 0)); if(eqdown(time + a[i].b, a[i].d)) { time += a[i].b; continue; } double res = time + a[i].b - a[i].d; time = a[i].d; while(fabs(res) > eps) { node u = q.top(); q.pop(); double cur = u.b - u.a*u.cost; if(eqdown(cur, res)) { res -= cur; ans += cur / u.a; } else { q.push(node(u.a, u.b, u.cost + res/u.a)); ans += res / u.a; cur -= res; res = 0; } } } return ans; } int main() { scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i = 0; i < n; i++) { scanf("%lf%lf%lf",&a[i].a, &a[i].b, &a[i].d); } sort(a, a+n); printf("%.2f\n", solve()); } return 0; }