UVa 1422 Processor

题意:

有 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;
}


你可能感兴趣的:(UVa 1422 Processor)