1014 Waiting in Line (30分)
Suppose a bank has 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:
- The space inside the yellow line in front of each window is enough to contain a line with M customers. Hence when all the N lines are full, all the customers after (and including) the (NM+1)st one will have to wait in a line behind the yellow line.
- Each customer will choose the shortest line to wait in when crossing the yellow line. If there are two or more lines with the same length, the customer will always choose the window with the smallest number.
- Customeri will take Ti minutes to have his/her transaction processed.
- The first N customers are assumed to be served at 8:00am.
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 customers 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, customer1 is served at window1 while customer2 is served at window2. Customer3 will wait in front of window1 and customer4 will wait in front of window2. Customer5 will wait behind the yellow line.
At 08:01, customer1 is done and customer5 enters the line in front of window1 since that line seems shorter now. Customer2 will leave at 08:02, customer4 at 08:06, customer3 at 08:07, and finally customer5 at 08:10.
Input Specification:
Each input file contains one test case. Each case starts with a line containing 4 positive integers: N (≤20, number of windows), M (≤10, the maximum capacity of each line inside the yellow line), K (≤1000, number of customers), and Q (≤1000, number of customer queries).
The next line contains K positive integers, which are the processing time of the K customers.
The last line contains 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.
Output Specification:
For each of the Q customers, print in one line the time at which his/her transaction is finished, in the format
HH:MM
whereHH
is in [08, 17] andMM
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 outputSorry
instead.Sample Input:
2 2 7 5 1 2 6 4 3 534 2 3 4 5 6 7
Sample Output:
08:07 08:06 08:10 17:00 Sorry
这题真的,模拟吐了,一直是19分,三个测试点没过,后来百度才知道,如果一个人的服务开始时间在17点之前,但是服务结束时间超过了17点,那这也算的。。。吐了
纪念一下:
首先理解题意:
假设一家银行有N个服务窗口。窗户前面有一条黄线,把等候区分成两部分(黄线里面和黄线外面)。顾客排队等候的规则是:
- 每个窗口前面的黄线内的空间只能容纳M个客户。因此,当所有N行都满时,(N*M+1)后的所有客户(包括)都必须在黄线后面排队等候。
- 每一位顾客在过黄线时都会选择最短的排队等候。如果有两条或两条以上相同长度的队,顾客总是会选择编号最小的窗口。
- 第i位顾客需要花费Ti分钟办理他的业务
- 第一批顾客在早上8点接待,然后17点下班
输入:
第一行四个数字n, m, k, q,分别代表银行有n个窗口,黄线和窗口中间排队最多排m个人,然后k代表总共有k个人需要办理业务,q是需要查询q次。
第二行k个数字,是1号到k号,每个人需要服务的时间。
第三行q个数字,输入需要查询的人,能够在几点办理完业务。
限制条件就是这四条:
按照题目中的案例,模拟一下过程:
刚开始,1 2 3 4在黄线内,567在黄线外等候
然后8点01,1号办理完业务;8点02,2号办理完业务;1和2 离开
那这时候56就可以进黄线内了,5号先选,因为8点01的时候1号就离开了,5肯定选择①号窗口,那么6只能进入②号窗口排队
3号需要办理6分钟,4号需要办理4分钟,所以3号在8点07离开,4号在8点06离开
所以7肯定进入②号窗口排队
5号在8点10分办理完业务,6号需要534分钟,直到17点才办理完业务,
所以7号如果办理业务的话,得到17点以后,但是银行17点下班。。
思路就是这么个思路了,需要一点点转换思维,加油奥利给~
代码:
#include <bits/stdc++.h>
using namespace std;
int timee[1005];
queue < int > line[200];
vector < int > windows[250], ans;
int n, m, k, q;
bool check() {
for (int i = 1; i <= n; i++) {
if (line[i].size() < m)
return true;
}
return false;
}
void join(int cur) {
int pp = 0, t = 1000;
for (int i = 1; i <= n; i++) {
if (line[i].size() == m) //如果正常窗口已经有M个人了,看下一个窗口
continue;
if (windows[i].back() < t) { //如果这个窗口服务到时间20,另一个窗口服务到时间30,那肯定选当前的
pp = i;
t = windows[i].back();
}
}
line[pp].push(cur);
}
int main() {
scanf("%d %d %d %d", & n, & m, & k, & q);
for (int i = 1; i <= k; i++) {
scanf("%d", & timee[i]);
}
int cur = 1; //第cur个人在黄线内
for (int p = 1; p <= m; p++) { //每列最多m个人
for (int j = 1; j <= n; j++) { //n个窗口
line[j].push(cur++);
}
if (cur > n * m)
break;
}
for (int i = 1; i <= n; i++) { //刚开始,每个窗口从时间0开始服务。
windows[i].push_back(0);
}
int t = 0;
while (t < k) {
for (int i = 1; i <= n; i++) {
if (line[i].empty()) //如果这个窗口前面没人了,跳过。
continue;
t = line[i].front(); //t是正在处理业务的人
line[i].pop();
int tmp = windows[i].back() + timee[t]; //t处理完业务后,这个窗口的服务时间到tmp
ans.push_back(tmp);
windows[i].push_back(tmp);
if (t == k)
break;
}
while (check() && cur <= k) { //check()是检查黄线内的容量,cur<=k是只有k个人办理业务
join(cur); //如果黄线内还有容量 且cur不超过k
cur++; //下一个人是cur++
}
}
/*for(int i=0;i<res.size();i++){
cout << i+1 << ' ' << res[i] << endl;
}*/
while (q--) {
int t;
scanf("%d", & t);
//如果这个人在17点之前赶上了,但是在17点之后结束,那也算
if (ans[t - 1] <= 540 || (ans[t - 1] > 540 && ans[t - 1] - timee[t] < 540)) {
printf("%02d:%02d\n", 8 + ans[t - 1] / 60, ans[t - 1] % 60);
} else {
printf("Sorry\n");
}
}
system("pause");
}