【PAT(甲级)】1014 Waiting in Line(详细分析了排队原理)

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

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

解题思路:

银行开了N个窗口,每个窗口在黄线内可以容纳M个人,多出来的人按顺序排在黄线外,哪个窗口先走人多出空位,人就去那个窗口接着排队。按照题目给的数据,一开始黄线内排队如下

1号窗口2号窗口

正在办理业务

8:00开始

编号1的客人(需要1min)
8:01离开

8:00开始

编号2的客人(需要2min)
8:02离开

8:01开始

编号3的客人(6min)
8:07离开

8:02开始

编号4的客人(4min)
8:06离开

在8:01分之后,编号1的客人办理完业务离开,此时,黄线外等候的编号5的客人就可以进入黄线内,在1号窗口前排队了,排队如下:

1号窗口2号窗口
正在办理业务

8:01开始

编号3的客人(还需要6min)

8:07离开

8:00开始

编号2的客人(还需要1min)

8:02离开

8:07开始

编号5的客人(3min)

8:10离开

8:02开始

编号4的客人(4min)

8:06离开

在8:02分之后,编号2的客人办理完业务离开,此时1号窗口人还满着,所以编号6的客人进入黄线内,在2号窗口排队。

1号窗口2号窗口
正在办理业务

8:01开始

编号3的客人(还需要5min)

8:07离开

8:02开始

编号4的客人(4min)

8:06离开

8:07开始

编号5的客人(3min)

8:10离开

8:06开始

编号6的客人(534min)

17:00离开

最后,在8:06分,编号4的客人离开,编号7的客人进入黄线内,在2号窗口前排队,所有人都进入了黄线。

1号窗口2号窗口
正在办理业务

8:01开始

编号3的客人(还需要1min)

8:07离开

8:06开始

编号6的客人(534min)

17:00离开

8:07开始

编号5的客人(3min)

8:10离开

17:00开始

编号7的客人(2min)

不办理

这样看应该就很清晰了,其中,我们发现进入窗口客人的开始时间就是前一个客人的离开时间,同时,黄线外等候的客人会在办理业务的客人的离开时间最早的窗口前排队(有点长,好好理解一下)

所以我们需要一个结构来存储客户的开始时间,所需时间,离开时间(等于开始时间+所需时间),一个队列来存储窗口前客户的信息,然后把每个客户都放到相应的窗口前算出他的信息即可。

易错点:

1. 在17:00前开始的,就算办理时间超过了17:00点银行也会帮他办理完业务;至于17:00(包括17:00点)才刚开始办理业务的,都不办理。

代码:

#include<bits/stdc++.h>
using namespace std;
int N,M,K,Q;
typedef struct Customer{//存储客户开始,花费,结束的时间 
	int start=0;
	int time;
	int end;
	//假定窗口数大于顾客数,则每个顾客开始的时间为0,也即早上8点 
};
int main(){
	cin>>N>>M>>K>>Q;
	Customer C[K+1];//存储K名顾客的时间下标从1开始 
	queue<Customer> windows[N+1];//存储每个窗口所服务的顾客信息 
	
	for(int i=1;i<=K;i++){//读取每个人所需要花费的时间 
		cin>>C[i].time;
		C[i].end = C[i].time;//理想状态下,每个顾客的离开时间就是处理时间 
	} 
	
	for(int i=1;i<=K;i++){
		int window = (i-1)%N+1;//按照顺序第i个人就是i窗口,大于N的重新按顺序从1号窗口开始排队 
		if(i<=N*M){
			if(i>N){//i<=N的情况就是理想状态不用管 
				C[i].start = windows[window].back().end;
				C[i].end = C[i].start+C[i].time; 
			}else{//这个else只是保持语句的完整性,不然下面的else就要出错了 
			}
			windows[window].push(C[i]);//把每个顾客按顺序塞进每个窗口
		}
		else{//哪个窗口先走人,就先去哪个窗口 
			int window = 1;
			for(int j=2;j<=N;j++){
				if(windows[j].front().end<windows[window].front().end)
				//每个队列的第一个人的结束时间最小,就是最先走 
					window = j;
			} 
			windows[window].pop();//让顾客出队 
			C[i].start = windows[window].back().end;
			C[i].end = C[i].start+C[i].time;
			windows[window].push(C[i]);//新顾客进入黄线就是入队 
		} 
	} 
	
	for(int i=0;i<Q;i++){
		int a;
		cin>>a;
		int HH=8;
		if(C[a].start/60+8>=17)
			cout<<"Sorry"<<endl;
		else
			printf("%02d:%02d\n",C[a].end/60+HH,C[a].end%60);
	}
	return 0;
}

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值