HDU 6180 Schedule【优先队列+模拟】

题目链接

题意:有一些任务,要用一些机器去做这些任务,给出每个任务的开始时间和结束时间。一台机器最多只能同时做一个任务,并且机器关掉不能再开,求在使用最少机器的情况下,最少的机器个数和最短的运行时间。

拿两个优先队列模拟…贪心的找现在空着的机器中做完上个任务最晚的那个,这样才能让机器等的时间最少。

代码里有详细解释。

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

int T;
int N;
ll cnt,sum;

struct Work{
    ll start,end;
}work[100000+10];

bool cmp(Work a,Work b){
    if (a.start!=b.start)
        return a.start<b.start;
    else
        return a.end<b.end;
}

// 空闲序列其实表示的是所有已经开始运行但现在没有任务在运行的机器
priority_queue < ll,vector<ll>,greater<ll> > working; // 小顶堆,工作机器序列
priority_queue < ll,vector<ll>,less<ll> > notworking; // 大顶堆,空闲机器序列

int main(){
    // freopen("1.txt","r",stdin);
    scanf("%d",&T);
    while (T--){
        while (!working.empty())    working.pop();
        while (!notworking.empty()) notworking.pop();
        cnt=0;
        sum=0;
        scanf("%d",&N);
        for (int i=1;i<=N;i++){
            scanf("%lld %lld",&work[i].start,&work[i].end);
        }
        sort(work+1,work+N+1,cmp);
        for (int i=1;i<=N;i++){
            // 从运行序列中找出所有比当前任务的开始时间早的
            // 也就是在当前任务开始前就已经完成了的加入空闲集合 
            while (!working.empty()&&working.top()<=work[i].start){
                ll tmp=working.top();
                working.pop();
                notworking.push(tmp);
            }
            // 如果此时空闲集合不为空,说明这个机器开着但是现在没有任务可做
            // 那么肯定是优先选择做完上个任务的时间晚的来做这个任务
            // 这样机器等的时间就少
            if (!notworking.empty()){
                ll tmp=notworking.top();
                notworking.pop();
                sum+=work[i].end-tmp; // 加上机器等的时间和做这个任务的时间
                working.push(work[i].end); // 加入运行序列
            }
            // 若果此时空闲集合为空,说明现在没有机器,那只能新开一台机器
            else{
                cnt++; // 新开一台机器
                sum+=work[i].end-work[i].start; // 加上做这个任务的时间
                working.push(work[i].end); // 加入运行序列
            }
        }
        printf("%lld %lld\n",cnt,sum);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值