Suppose a bank has N N N windows open for service. There is a yellow line in
front of the windows which devides the waiting area into two parts. The rules
for the customers to wait in line are:
Now given the processing time of each customer, you are supposed to tell the
exact time at which a customer has his/her business done.
For example, suppose that a bank has 2 windows and each window may have 2
custmers waiting inside the yellow line. There are 5 customers waiting with
transactions taking 1, 2, 6, 4 and 3 minutes, respectively. At 08:00 in the
morning, c u s t o m e r 1 customer_1 customer1 is served at w i n d o w 1 window_1 window1 while c u s t o m e r 2 customer_2 customer2 is served at
w i n d o w 2 window_2 window2 . C u s t o m e r 3 Customer_3 Customer3 will wait in front of w i n d o w 1 window_1 window1 and c u s t o m e r 4 customer_4 customer4
will wait in front of w i n d o w 2 window_2 window2 . C u s t o m e r 5 Customer_5 Customer5 will wait behind the yellow
line.
At 08:01, c u s t o m e r 1 customer_1 customer1 is done and c u s t o m e r 5 customer_5 customer5 enters the line in front of
w i n d o w 1 window_1 window1 since that line seems shorter now. C u s t o m e r 2 Customer_2 Customer2 will leave at
08:02, c u s t o m e r 4 customer_4 customer4 at 08:06, c u s t o m e r 3 customer_3 customer3 at 08:07, and finally c u s t o m e r 5 customer_5 customer5
at 08:10.
Each input file contains one test case. Each case starts with a line
containing 4 positive integers: N N N ( ≤ 20 \le 20 ≤20 , number of windows), M M M (
≤ 10 \le 10 ≤10 , the maximum capacity of each line inside the yellow line), K K K (
≤ 1000 \le 1000 ≤1000 , number of customers), and Q Q Q ( ≤ 1000 \le 1000 ≤1000 , number of customer
queries).
The next line contains K K K positive integers, which are the processing time of
the K K K customers.
The last line contains Q Q Q positive integers, which represent the customers
who are asking about the time they can have their transactions done. The
customers are numbered from 1 to K K K .
For each of the Q Q Q customers, print in one line the time at which his/her
transaction is finished, in the format HH:MM
where HH
is in [08, 17] and
MM
is in [00, 59]. Note that since the bank is closed everyday after 17:00,
for those customers who cannot be served before 17:00, you must output Sorry
instead.
2 2 7 5
1 2 6 4 3 534 2
3 4 5 6 7
08:07
08:06
08:10
17:00
Sorry
银行有N个窗口, 每个窗口允许排M个顾客. 一大早8点所有顾客商量好蜂拥而入,
那么情况有两种: 1, 顾客全部能排在队伍里; 2, 顾客人数太多, 有人排在外面,
要等前面的顾客完成离开, 再进入列列.
注意点:
解读题目时提到可以存在两种情况, 我将这两种情况合并了一下:
顾客一共有K个, 如果K<=M*N
, 那么我用下面这图表示人次的流动情况(E表示入列, D表示
出列, -表示此时无此操作):
时间顺序或者操作顺序-->
出列: -----------------DDD...(K*D)...DDD
入列: EEE...(K*E)...EEE-----------------
即表示一起进行K次入列, 然后一起进行K次出列, 就完成了.
如果K>M*N
, 那么其中有一段时间会交替有人出列/入列, 表示起来就是:
时间顺序或者操作顺序-->
出列: ----(M*N)-----DDDDDD...(K*D)...DDD
入列: EEE...(K*E)...EEEEEE----(M*N)-----
这表示前MN次只有入列, 中间有顾客出列, 有顾客入列, 最后MN次只有出列.
总结这两种情况, 都是前K次是入列, 后K次是出列, 只需再计算出总的操作次数(出入记为
一次)即可, 其实就是max(2*K, M*N+K)
.
这样代码结构就是
循环max(2*K, M*N+K)次:
如果是后K次:
出列
如果是前K次:
入列
数据结构:
用一个数组(长度至少为K+1, 后面解释)先记录每个顾客的所需时间. 后面操作将这个时间
更新为顾客入列时间.
时间为距离早8点的分钟数.
如实按顾客编号(即从1开始)记录, 角标为0的元素保持为0.
用N个队列模拟相关过程, 记录内容为顾客标号, 但是队列长度至少为M+1(后面解释)
操作主要在入列时(因为入列时间很重要)
入列时:
出列时:
最新代码@github,欢迎交流
#include
#define LATE_FLAG -1
#define FORWARD(I) ((I) = ((I) == 10) ? 0 : ((I) + 1))
#define TIME_FRONT(I) time[queue[I][front[I]]]
#define TIME_REAR_PREVIOUS(I) time[queue[I][rear[I] == 0 ? 10 : (rear[I] - 1)]]
int main()
{
int N, M, K, Q, query;
int time[1000], queue[20][11] = {{0}};
int front[20] = {0}, rear[20] = {0}, length[20] = {0};
scanf("%d %d %d %d", &N, &M, &K, &Q);
for(int i = 1; i <= K; i++)
scanf("%d", time + i);
/* Total number of operations */
int count = (K < M * N) ? (2 * K) : (K + M * N);
/* Doing dequeues and enqueues for every customer */
for(int i = 1; i <= count; i++)
{
if(i > count - K) /* Dequeue in the last K operations */
{
/* Find the next customer */
int time_span = 9999, next = -1;
for(int j = 0; j < N; j++) if(length[j])
{
if(TIME_FRONT(j) < time_span)
next = j, time_span = TIME_FRONT(j);
else if(next == -1 && TIME_FRONT(j) == LATE_FLAG)
next = j;
}
/* Dequeue */
FORWARD(front[next]);
length[next]--;
}
if(i <= K) /* Enqueue in the first K operations */
{
/* Find shortest queue */
int shortest = 0;
for(int j = 0; j < N; j++)
if(length[shortest] > length[j])
shortest = j;
/* Set flag or add time */
int previous_time = TIME_REAR_PREVIOUS(shortest);
if(previous_time >= 9 * 60 || previous_time == LATE_FLAG)
time[i] = LATE_FLAG;
else
time[i] += previous_time;
/* Enqueue */
queue[shortest][rear[shortest]] = i;
FORWARD(rear[shortest]);
length[shortest]++;
}
}
/* Read queries and print answers */
for(int i = 0; i < Q; i++)
{
scanf("%d", &query);
if(time[query] != LATE_FLAG)
printf("%02d:%02d\n", 8 + time[query] / 60, time[query] % 60);
else
printf("Sorry\n");
}
return 0;
}