UVA 1153 Keep the Customer Satisfied

来源:互联网 发布:扫雷技巧红包软件 编辑:程序博客网 时间:2024/05/20 07:58

题意:有n个工作,已知每个工作需要的时间q和截止时间d(必须在此之前完成),最多能完成多少个工作?工作一次只能做一个,第一项工作的开始时间不早于0时刻

解题思路:贪心+优先队列.这道题目首先要注意的是输出的是工作所需时间和截止时间,所以说该工作最晚的开始时间是d-q,在这个时间之前该工作都可以被做。如果工作的开始时间大于等于上一个工作的结束时间,那么完成工作数加1,更新结束时间,同时将该工作的所需时间插入队列;如果工作的开始时间小于上一个工作的结束时间,那么就要比较该工作所需时间和队首元素(也就是之前完成的工作中所需时间最长的那个),如果该工作所需时间短,那么就删除队首元素,也就是说把之前完成的所需时间最长的那个工作去掉,重新加入该工作,因为这样删除一个增加一个,完成的工作数是不变的,而所需时间短的,它完成工作的结束时间也早,就会有更多的时间去完成更多的工作。这里用的是结构体,所以要写优先队列重载

代码:

#include <iostream>#include <algorithm>#include <string>#include <cstring>#include <cstdio>#include <cmath>#include <queue>using namespace std;struct P{    int last,ed;    bool operator <(const P &k) const//优先队列的重载    {        return last>k.last;    }} p[800000+5];bool cmp(P p1,P p2){    return p1.ed<p2.ed;}int main(){    int t;    cin>>t;    while(t--)    {        int n;        cin>>n;        for(int i=0; i<n; i++)        {            cin>>p[i].last>>p[i].ed;        }        sort(p,p+n,cmp);        int temp=0,ans=0;        priority_queue<int> q;        for(int i=0; i<n; i++)        {            if(p[i].ed-p[i].last>=temp)            {                ans++;                temp+=p[i].last;                q.push(p[i].last);            }            else            {                if(!q.empty())                {                    int x=q.top();                    if(x>p[i].last)                    {                        q.pop();                        temp-=x;                        q.push(p[i].last);                        temp+=p[i].last;                    }                }            }        }        cout<<ans<<endl;        if(t)cout<<endl;    }    return 0;}


原创粉丝点击