题意:
有 n 个任务,每个任务有 3 个参数,r, d,w。表示必须在时间 [ r, d ] 之内执行,任务量为 w。
处理器的执行速度可以变化,当速度为 s 时,一工作量为 w 的任务要执行 w / s 个单位时间。任务不一定连续执行,
可以分块执行,求最小完成任务的速度。速度可以是任意整数。
分析:
先将这些任务按开始时间由小到大排序,模拟处理器按时间处理任务。然后二分法求最优解。
求解时枚举每个单位时间,将满足条件的任务放入优先队列,结束时间(d)越小越先出队列,因为要把 d 小的先完成。
代码:
#include <cstdio> #include <iostream> #include <algorithm> #include <queue> #define for1(i, a, b) for(int i = a; i <= b; i++) using namespace std; const int maxn = 10000 + 10; int n; struct Work { int r, d, w; friend bool operator < (Work a, Work b) { //优先队列中的 work,d 越小越先出队列 return a.d > b.d; } } work[maxn]; bool cmp(Work a, Work b) { return a.r < b.r; } bool cleck(int cur) { priority_queue<Work> Q; int c = 0; for1(i, 1, 20000){ int sum = cur; while(work[c].r < i && c != n) Q.push(work[c++]); while(sum && !Q.empty()){ Work cnt = Q.top(); Q.pop(); if(cnt.d < i) return false; //当前任务的结束时间小于此时刻,这个速度完不成! if(cnt.w > sum){ //此单位时间不能做完当前任务 cnt.w -= sum; //能做多少做多少 sum = 0; Q.push(cnt); //放入队列,下次再做 } else{ //能完成当前任务 sum -= cnt.w; } } if(c == n && Q.empty()) return true; //全部任务都完成 } if(c == n && Q.empty()) return true; return false; } int main() { int t; scanf("%d", &t); while(t--){ scanf("%d", &n); for1(i, 0, n-1) scanf("%d%d%d", &work[i].r, &work[i].d, &work[i].w); sort(work, work + n, cmp); //先按开始时间由小到大排序 int L = 0, R = 10000000; //n最大为10000,w最大为1000,故最大速度为10000000 while(L < R){ //二分求最优解 if(L == R - 1) break; int D = (L + R) >> 1; if(cleck(D)) R = D; else L = D; } printf("%d\n", R); } return 0; }