顾客就是上帝
LUCY是一家高级私人银行的总经理,该银行只服务VIP顾客,而且需要提前一天预约。
银行有五个柜台,每个柜台拥有独立的队列,每天服务9小时,每6秒作为一个预约区间;
每天最多服务1000个顾客,每个顾客可以预约任意到店时间(1 至 5000区间)和办理的业务;
根据业务经验,LUCY可以精确预测服务每一个顾客的所需时间(最少6秒,最多不超过1分钟,即最多10个区间);
顾客就是上帝,每一个顾客办理业务后都会给出评价,到店1分钟(10个时间区间)内完成业务办理的话会得到好评,否则差评。
LUCY 为了0差评,会用最优方案安排每个柜台的等候队列。
(先到店的先进队,同一时间到店的按预约先后顺序进队) 当柜台被占用,该柜台的队伍就必须等待。
为了银行利益最大化,有时候无需开放全部5个柜台即可0差评; LUCY总经理能够安排开放最少数量的柜台且0差评。
若已知明天所有顾客的到店时间和业务办理时间, 你能跟LUCY一样计算出最少开放的柜台数量并获0差评吗?
Input
第一行给出case数量TC,后面给出TC个case。
每个case第一行给出预约的顾客数量N (1 <= N <= 1000) ,
接着N行按顺序给出顾客到店时间区间Ti (1 <= Ti <= 5000) 和业务办理时间Li (1 <= Li <= 10)。
Output
输出”#t” ,接着空格,然后输出答案(为了获得0差评,最少的开放的柜台数),
若开放5个柜台都无法0差评,输出 -1 。
Sample Input
5
2
2 7
5 8
3
1 3
2 3
3 5
3
1 5
2 4
3 8
50
1 4
2 10
3 10
3 6
4 10
5 3
5 10
5 10
7 6
7 3
9 10
12 10
13 3
13 1
17 6
17 6
18 8
19 9
19 10
20 3
21 10
22 9
23 10
23 10
25 10
26 10
26 10
27 10
28 6
31 9
32 8
32 1
33 10
34 4
34 6
35 10
37 9
38 4
39 1
40 6
40 1
41 9
43 6
44 3
45 3
46 3
46 10
47 1
49 3
49 9
100
2 2
6 6
21 6
32 2
50 2
50 7
55 8
89 4
92 10
101 1
104 1
115 4
116 2
117 4
124 1
126 9
134 8
159 6
177 3
186 5
191 4
198 8
199 3
201 7
203 9
205 3
223 10
236 2
239 1
250 6
272 1
292 9
296 1
304 9
307 7
309 6
312 4
324 5
325 1
330 5
332 8
343 9
349 5
364 4
371 3
381 4
384 8
404 8
412 10
434 8
438 4
444 2
469 6
473 3
492 10
501 9
529 9
539 9
542 7
558 9
569 2
580 9
582 10
610 8
637 7
637 8
649 4
653 1
658 4
668 1
678 1
683 2
710 1
721 8
729 9
749 3
759 10
767 8
775 1
776 5
779 1
789 3
790 6
796 2
810 9
812 5
816 4
822 7
849 7
874 1
876 3
893 8
895 3
901 3
961 9
961 1
970 3
977 8
985 8
989 10
Sample Output
#1 2
#2 1
#3 2
#4 -1
#5 3
CODE:
#include<iostream>
#include<stdio.h>
const int SIZE = 1001;
int T[SIZE], L[SIZE];
int NUM;
bool isDfsSucces;//是否递归到最后一个顾客
bool isRetartDfs;//cpu全部空闲,重新dfs
int dfsDeepth; //递归的深度
int N;
void dfs(int index, int cpu[])
{
if(index >= N)
{
isDfsSucces = true;
return;
}
if(isRetartDfs)
{
return;
}
//表示下一个的顾客预约时间和上一个顾客的时间间隔。
int waitTime = T[index] - T[index-1];
if(waitTime > 0)
{
for(int i = 0; i < NUM; i++)
{
cpu[i] -= waitTime;
if(cpu[i] < 0) //表示处理完index-1,到index开始时间的间隔。大于0,cpu[i]表示index需要等待的时间
{
cpu[i] = 0;
}
}
}
//检查所有CPU是否都不用等待
waitTime = 0;
for(int i = 0; i < NUM; i++)
{
if(cpu[i] > 0)//表示需要等待
{
waitTime = 1;
break;
}
}
//如果都是空闲,表示这个时候所有CPU都没有事件处理了,跳出当前dfs,进入while循环。
if(waitTime == 0)
{
isRetartDfs = true;
dfsDeepth = index;
return;
}
for(int i = 0; i < NUM; i++)
{
if(cpu[i] + L[index] > 10)//服务大于10
{
continue;
}
bool sameCpuState = false;
//剪枝,有相同的CPU就直接跳过
for(int k = 0; k < i; k++)
{
if(cpu[k] == cpu[i])
{
sameCpuState = true;
break;
}
}
if(sameCpuState)
{
continue;
}
int c[5] = {0};
for(int j = 0; j < NUM; j++)
{
c[j] = cpu[j];
}
//加在其中一个进行递归处理,继续深度递归处理
c[i] += L[index];
dfs(index+1, c);
if(isDfsSucces || isRetartDfs)
{
return;
}
}
}
bool useCpuNum(int num)
{
NUM = num;
isDfsSucces = false;
isRetartDfs = true;
dfsDeepth = 0;
int cpu[5] = {0};
while(isRetartDfs)
{
if(dfsDeepth == N - 1)
{
return true;
}
isRetartDfs = false;
cpu[0] = L[dfsDeepth];
dfs(dfsDeepth+1, cpu);
}
return isDfsSucces;
}
int main()
{
int i,j,k,t;
int ans;
int TC;
scanf("%d", &TC);
for(t = 1; t <= TC; t++)
{
//input data
scanf("%d", &N);
for(i = 0; i < N; i++)
{
scanf("%d %d", &T[i], &L[i]);
}
ans = -1;
//分别遍历1,2,3,4,5个CPU是否可行
if(useCpuNum(3))
{
if(useCpuNum(2))
{
if(useCpuNum(1))
{
ans = 1;
}
else
{
ans = 2;
}
}
else
{
ans = 3;
}
}
else if(useCpuNum(4))
{
ans = 4;
}
else if(useCpuNum(5))
{
ans = 5;
}
printf("#%d %d\n", t, ans);
}
return 0;
}
/**************************************************************
Problem: 1111
User: seaicelin
Language: C++
Result: Accepted
Time:8 ms
Memory:1684 kb
****************************************************************/