HDU 6180 Schedule

来源:互联网 发布:淘宝怎么开网店多少钱 编辑:程序博客网 时间:2024/06/05 05:59

Schedule

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

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 timeend 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

Source
2017 Multi-University Training Contest - Team 10


题意:
有n个加工需求,并给出开始和结束时间,对于每台机器不能同时加工两个零件,问最少需要多少台机器,并求出使用最少机器时所有机器工作的最小时间和。

思路:

题解:In this problem, we must assign each task in optimal way so that minimize the number of working machines first and when we use minimum number of machines, also minimize the total working time of all machines. So, we can use greedy method to solve this problem. First, we must sort all the tasks in increasing order of their starting time. Then, selecting the tasks in that order, we must choose the machine which is available to assign current task and most recently finished its working, and assign current task to that machine. When there isn’t such machine, we must assign current task to a new machine. By doing so, we can minimize both the number of working machine and total working time.
大概就是先按照开始时间对所有需求排序,然后从小开始遍历。
[1]如果有结束加工时间小于当前需要开始时间的,那么选择结束得最晚的满足需求的机器(比较好理解,因为这样可以减少中间空闲的时间,使得最后加工时间和最小)。
[2]如果没有能够使用的机器则说明需要增加一台。

我的做法:
在我的想象中有一个数轴,然后这些schedule就像一些长度不同的贴纸吧,然后往数轴上贴,显然最厚的那部分说明了一共需要多少台机器,至于总时间的计算,某一层的开始时间就是那层最左边的schedule的开始时间,结束时间就是最右边的schedule的结束时间。
先按照开始时间排序(注意如果有开始时间和结束时间相同的情况,开始时间优先)。引入两个变量,sum代表遍历到当前schedule的层数,从左到右遍历,遇到timestart则sum++,遇到timeend则sum–;再引入一个maxx,表示遍历到当前schedule时sum的最大值。从左往右遍历时,如果出现sum>maxx的情况,则说明需要增加一台机器(也就是说这个schedule是这台机器开始工作的时间,我们把它记录下来),然后再从右往左遍历,同理遇到sum>maxx的情况则说明这个schedule是这台机器的结束时间,最后就可以计算总时间。

代码如下:

#include<bits/stdc++.h>#define ll long longusing namespace std;struct ss{    ll pos;    int lr;}q[200005];//vector<ss> q;ll in[100005],out[100005];bool compare(ss x,ss y){    if(x.pos<y.pos)        return true;    if(x.pos==y.pos && x.lr==1)        return true;    return false;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n;        scanf("%d",&n);        int i;        ll x=0;        for(i=0;i<n;i++)        {            ll a,b;            scanf("%lld %lld",&a,&b);            q[x].lr=0;q[x++].pos=a;            q[x].lr=1;q[x++].pos=b;        }        sort(q,q+2*n,compare);        ss *iter;        ll sum=0,maxx=0;        int num=0;        for(iter=q;iter<q+2*n;iter++)        {            if((*iter).lr==0) sum++;            else sum--;            if(sum>maxx)            {                maxx=sum;                in[num++]=(*iter).pos;            }        }        sum=0;num=0;maxx=0;        for(iter=q+2*n-1;iter>=q;iter--)        {            if((*iter).lr==1) sum++;            else sum--;            if(sum>maxx)            {                maxx=sum;                out[num++]=(*iter).pos;            }        }        ll res=0;        for(i=0;i<maxx;i++)        {            res+=out[i]-in[i];        }        printf("%lld %lld\n",maxx,res);    }}