杭电-6180

最小机器调度问题

Schedule

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


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个时间表,他们分别有自己的开始时间和结束时间,同时,也有很多机器,时间表上的时间是使用机器的时间,然而,一台机器不能在重复的时间被使用,所以,要完成时间表的任务,可能需要多台机器,题目要求的就是符合要求的最少机器数和相应时间之和。


解题分析:首先,假设机器可以在同一时刻被重复使用,那么最短时间和即为每个时间段之和,但是,现在条件限制机器不能同一时间重复使用,那么必然有机器在执行完一个任务后等待下一个任务的过程,其中的等待时间也要被计入总时间中,而等待时间是下一个时间段的开始时间减去之前时间段的结束时间。所以最短时间可以用每个时间段之和加上等待时间。同时,我们将我每个时间段的开始时间和结束时间拆开,利用结构体存储,用flag = 1标志它是开始时间,flag = 2 标识它为结束时间。对所有时间点进行从小到大排序,用mach记录变化机器数,如果遇左节点,mach++,遇右节点mach--,mach最大值即为最少机器数,同时将结束时间存入栈中,下一时间段的开始时间减去栈顶元素即为等待时间。

演示步骤:

1

3

1 3

2 5

4 6
经sort排序后:

时刻: 1    2    3    4    5   6

flag : 1    1    2    1    2   2


AC代码:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<stack>
using namespace std;

struct Nodes{
	int T;//时间点 
	int flag;//状态 
}node[300000];

int cmp(Nodes a , Nodes b){
	if(a.T != b.T ) return (a.T < b.T);
	else return (a.flag > b.flag );
	//如果相等,让状态为结束的点排前 , 
	//因为后面会有开始点状态减去栈中结束状态点,求等待时间 
}

int main(void){
	int x;
	scanf("%d",&x);
	while(x--){
		int count;
		int num = 0;
		int i;
		int mach = 0;
		int ans_mach = 0;
		long long  ans_sum = 0;//本题数据不用long long会超时; 
		stack<int>endtime;//结束时刻存放数组 
		scanf("%d",&count);
		while(!endtime.empty()){
			endtime.pop(); 
		}
		for(i=0;i<count;i++){
			 scanf("%d",&node[num].T);
			 scanf("%d",&node[num+1].T);
			 node[num].flag = 1;
			 node[num+1].flag = 2;
			 ans_sum = ans_sum + ( node[num+1].T - node[num].T);
			 num = num + 2;
		}
		sort(node,node + count*2,cmp);
		for(i=0;i < num ; i++){
			if(node[i].flag == 1){
				mach++; 
				if(!endtime.empty())
				{
					int t = endtime.top() ;
					endtime.pop(); 
					ans_sum = ans_sum + (node[i].T - t);//算出等待时间 
				}	
			}
			else{
				mach--;
				endtime.push(node[i].T); 
			}
			ans_mach = max(ans_mach,mach); 
		}
		printf("%d %lld\n",ans_mach,ans_sum);
	}
}



评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值