uva 1153 顾客是上帝(贪心)

uva 1153 顾客是上帝(贪心)

有n个工作,已知每个工作需要的时间q[i]和截止时间d[i](必须在此前完成),最多能完成多少个工作?工作只能串行完成,第一项任务开始的时间不早于时刻0.

这道题算比较难的贪心了。解法是维护一个关于所有选择的时间的大根堆。将所有工作按照截止时间排序(将二维问题转化为一维问题),然后依次考虑每一个工作。如果当前的总时间t,加上当前工作的时间t1,小于等于当前工作的截止时间d1,那么直接把当前工作加入大根堆中。如果t+t1>d1,说明如果做这个工作,就超时了,所以要考虑该不该做这个工作的问题。如果t1<大根堆顶的时间,说明如果把前面的一个工作消除掉,再做这个工作,时间能更短,我们当然选择把这个工作压到堆里去。如果t1>大根堆顶,说明这个工作是不能替换的。

插一句:贪心真是一种玄学的东西。。很多时候贪心要跟着感觉走,因为根本证明不出来~~~~~

#include <queue>
#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn=8e5+5;

int T, n;
priority_queue<int> q;
struct Work{
    int q, d;
}w[maxn];

bool cmp1(Work &x, Work &y){
    return x.d<y.d; }

int main(){
    scanf("%d", &T);
    while (T--){
        while (!q.empty()) q.pop();
        scanf("%d", &n);
        for (int i=0; i<n; ++i)
            scanf("%d%d", &w[i].q, &w[i].d);
        sort(w, w+n, cmp1);
        int tott=0, ans=0, maxelmt;
        for (int i=0; i<n; ++i){
            if (tott+w[i].q<=w[i].d){ //如果放的下就放
                tott+=w[i].q; ++ans;
                q.push(w[i].q);
            } else {
                maxelmt=q.top();
                if (maxelmt>w[i].q){ //如果换了更优就换
                    q.pop(); q.push(w[i].q);
                    tott=tott-maxelmt+w[i].q; }
            }
        }
        printf("%d\n", ans);
        if (T) puts("");
    }
    return 0;
}
posted @ 2018-03-03 20:57  pechpo  阅读(168)  评论(0编辑  收藏  举报