1153 - Keep the Customer Satisfied(贪心)

又是一道经典的贪心算法题目 。 乍看题目,想到了紫书一开始讲的区间问题(给定一些区间,选择尽可能多的不相交区间),和另一个经典问题:“活动安排”  的实质是一样的。

但是本题又和区间问题不同,因为区间起点未知,我们所知道的仅仅是等待时间和截至时间,但是其实贪心思想是一致的,即:尽可能的给后面的人留下更多时间,满足当前所用时间最少。 因此可以写出贪心算法 : 按照截至时间排序,将元素的消耗时间加到优先队列里,这样队首元素就是消耗时间最长的人,如果加上当前的人时间超过了他的截至时间,那么将队首元素(队列中消耗时间最多的人)删除。

 不难发现对于该题,这样的做法是正确的。我们可以用反证法来加以证明:加入当前这个人之后,如果时间没有超出他的截止时间,那么这样是最好的。 如果超出了,那么肯定要牺牲一个人,为了给后面的人留出更多的时间,所以要删除消耗时间最长的人。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 800000 + 5;
int T,n;
struct node {
    int l,r;
}a[maxn];
bool cmp(node a,node b) {
    return a.r < b.r ;            //**
}
int main(){
    scanf("%d",&T);
    while(T--) {
        scanf("%d",&n);
        for(int i=0;i<n;i++) scanf("%d%d",&a[i].l,&a[i].r);
        sort(a,a+n,cmp);
        priority_queue<int> q;
        int ans = 0,time = 0;
        for(int i=0;i<n;i++) {
            q.push(a[i].l);
            int t = q.top();          //加入当前的人
            time += a[i].l;
            ans ++;
            if(time > a[i].r) { 
                time -= t;  q.pop(); ans --; //删除消耗时间最长的人,为后面的人留出更多的时间
            }
        }
        printf("%d\n",ans);
        if(T) printf("\n");
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值