HDU 6180 Schedule(任务调度 贪心策略 17多校第十场)

  • 题目大意
    有n个任务,每个任务有一个起始时间和终止时间,一台机器一个时间最多处理一个任务,一台机器的运行时间定义为这台机器处理的任务中第一个任务开始的时间到最后一个任务结束的时间。
    问你最少需要多少台机器,在最少机器数量的情况下所有机器总的时间花费是多少.
  • 分析
    这种区间任务调度问题通常可行的一种实现方式是将左右端点看成独立的点来处理(用01来表示是左端点还是右端点),排一次序依次处理。
    符号约定
    total :记录在扫描的过程中当前开启的机器数目
    now :记录当前正在使用的机器数
    那么我们可以得到这样的贪心策略

    1. 如果遇到的是左端点:
      1. if(total==now)total++;now++; //当前已经开启的机全在使用,这个时候就需要新开一台
      2. if(total>now)now++; //有空闲的机器就使用空闲的机器
    2. 如果遇到的是右端点:
      now

    这样我们就可以找到最少的机器数
    总的花费时间就是每台机器的结束时间之和减去每台机器的开始时间之和
    有一条贪心策略就是当有空闲的机器可用时我们用结束最晚的那个
    在每次新开机器的时候我们记录下开启的时间就可以得到总的开启时间
    我们用一个栈来保存有机器空出时的结束时间,并在有新任务给空闲机器的时候将栈顶弹出(也就是结束时间最晚的那个),最后栈中的元素就一定是全部开启的机器的结束时间了

  • 代码

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<map>
#include<algorithm>
#include<set>
#include<stack>
using namespace std;
#define LL long long int
const int MAXN=200055;
int T;
LL n;
LL total;
LL now;
LL sum_start_time;
LL sum_end_time;
struct Node
{
    LL x;
    bool is_head;
}node[MAXN];
int nodecount;
inline void getInt(int* p) {
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    }
    else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}
void Init()
{
    nodecount=0;
    total=0;
    now=0;
    sum_start_time=0;
    sum_end_time=0;
}
void Add_node(LL x,bool is_head)
{
    node[++nodecount].x=x;
    if(is_head==1)node[nodecount].is_head=1;
    else node[nodecount].is_head=0;
}
int cmp(Node a,Node b)
{
    if(a.x!=b.x)return a.x < b.x;
    else return a.is_head < b.is_head;
}
void In()
{
    int  s,t;
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&s,&t);
         //getInt(&s);getInt(&t);
        Add_node(s,1);
        Add_node(t,0);
    }
}
void Work()
{
    stack<LL> St;
    sort(node+1,node+2*n+1,cmp);
    for(int i=1;i<=2*n;i++)
    {
        if(node[i].is_head==0)
        {
            now--;
            St.push(node[i].x);
        }
        else
        {
            if(total==now){total++;now++;sum_start_time+=node[i].x;}
            else {now++;St.pop();}
        }
    }
    while(!St.empty())
    {
        LL t=St.top();
        St.pop();
        sum_end_time+=t;
    }
    printf("%lld %lld\n",total,sum_end_time-sum_start_time);
}
int main()
{
   //freopen("in.txt","r",stdin);
  //  freopen("out1.txt","w",stdout);
    scanf("%d",&T);
    while(T--)
    {
        Init();
        In();
        Work();
    }
    return 0;
}
/*
2
3
1 3
4 6
2 5

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值