【UVa1153】Keep the Customer Satisfied 顾客是上帝(贪心)

题目描述:

题目链接
n(n800000) 个工作,已知每个工作需要的时间 qi 和截止时间 di (不必在此之前完成),最多能完成多少个工作?工作只能串行完成。第一项任务开始的时间不早于时刻 0

—-摘自《算法竞赛入门经典》

算法:

贪心

做法:

可以想到的是如果知道了要完成的这些工作,那么就应该不停歇的把工作完成,即两个工作之间不应有空闲,这是最优的。

把所有工作按 d 从前往后排序,记录一个 t 代表已用的时间。现在要处理第 i 个任务,如果 t+qidi ,那么就“暂时”完成这个工作;如果 t+qi>di ,就看看之前完成的工作中耗时最多的那个 j ,如果 dj>di ,那么就可以撤销 j ,换成 i ,因为耗时长又截止时间短的工作不如耗时短而截止时间长的工作。

我为什么想不到呢?
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;

const int N=800010;
int n, T;

struct Work{
    int q, d;
    bool operator < (const Work & rhs) const {
        return d<rhs.d;
    }
} w[N];

int ans = 0 , t;
priority_queue <int> Q;         // 用优先队列找到已完成的耗时最长的工作的耗时  

int main(){
    scanf("%d", &T);
    while(T--){
        scanf("%d", &n);
        for(int i=1; i<=n; ++i) scanf("%d%d", &w[i].q, &w[i].d);
        sort(w+1, w+n+1);
        t = 0;
        while(!Q.empty()) Q.pop();
        for(int i=1; i<=n; ++i){
            if(t+w[i].q<=w[i].d){
                Q.push(w[i].q);
                t += w[i].q;
            }else{
                if(!Q.empty() && Q.top()>w[i].q){
                    t = t-Q.top()+w[i].q;
                    Q.pop();
                    Q.push(w[i].q);
                }
            }
        }
        printf("%d\n", Q.size());
        if(T) puts("");
    }
    while(1);
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值