Hdu 6180 Schedule【贪心】

探讨如何确定最少数量的机器来执行一系列任务,并计算这些机器的最小工作时间总和,采用区间覆盖的方法解决该问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Schedule

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 153428/153428 K (Java/Others)
Total Submission(s): 539    Accepted Submission(s): 204


Problem Description
There are N schedules, the i-th schedule has start time si and end time ei (1 <= i <= N). There are some machines. Each two overlapping schedules cannot be performed in the same machine. For each machine the working time is defined as the difference between timeend and timestart , where time_{end} is time to turn off the machine and timestart is time to turn on the machine. We assume that the machine cannot be turned off between the timestart and the timeend
Print the minimum number K of the machines for performing all schedules, and when only uses K machines, print the minimum sum of all working times.
 

Input
The first line contains an integer T (1 <= T <= 100), the number of test cases. Each case begins with a line containing one integer N (0 < N <= 100000). Each of the next N lines contains two integers si and ei (0<=si<ei<=1e9).
 

Output
For each test case, print the minimum possible number of machines and the minimum sum of all working times.
 

Sample Input
1 3 1 3 4 6 2 5
 

Sample Output
2 8

题目大意:


给出N个执行任务的区间【L,R),问你最少用多少台机器能够完成任务,并且输出最少的每台机器的工作时间总和。

一台机器如果开启了,再关闭之后就不能开启了。


思路:


我们知道,区间覆盖数最大的值,就是我们使用的最少机器数量。


接下来考虑如何搞这个时间总和:

①如果我们能够知道一台机器的开启时间和结束时间就很容易搞定这个问题了、

②那么设定L【i】,R【i】分别表示第i台机器的开启时间和关闭时间。

③那么我们将所有任务的区间的点按照从小到大排序,那么我们从左向右扫,每遇到一个任务起点,sum++,遇到一个任务终点,sum--.我们知道,当sum>ans的时候,我们就需要开启一台新的机器,并且更新ans=sum;这样我们就能够很容易处理出L【i】;

④那么反过去,我们从后向前扫,遇到一个任务终点,sum++,遇到一个任务起点,sum--,我们知道,当sum>ans的时候,我们就相当于关闭了一台机器,并且更新ans=sum

这样我们能够很容易处理出R【i】;

⑤最终的时间总和就是ΣR【i】-L【i】


Ac代码:

#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
struct node
{
    int op,x;
}a[250000];
int L[2500000];
int R[2500000];
int Sum[2500000];
int cmp(node a,node b)
{
    if(a.x==b.x)return a.op<b.op;
    return a.x<b.x;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        int cnt=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int x,y;scanf("%d%d",&x,&y);
            a[cnt].x=x;
            a[cnt++].op=1;
            a[cnt].x=y;
            a[cnt++].op=-1;
        }
        int ans=0;
        int cont=0;
        int sum=0;
        sort(a,a+cnt,cmp);
        for(int i=0;i<cnt;i++)
        {
            sum+=a[i].op;
            if(sum>ans)
            {
                ans=sum;
                L[ans]=a[i].x;
            }
        }
        ans=sum=0;
        for(int i=cnt-1;i>=0;i--)
        {
            sum-=a[i].op;
            if(sum>ans)
            {
                ans=sum;
                R[ans]=a[i].x;
            }
        }
        __int64 output=0;
        for(int i=1;i<=ans;i++)
        {
            output+=R[i]-L[i];
        }
        printf("%d %I64d\n",ans,output);
    }
}













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值