Pat【甲级】 1017 Queueing at Bank 银行排队(附中文题目) 模拟

这一系列是为了准备2021年3月的pat甲级,目标是把pat甲级的150多道题目刷完并写相应题解,对一些在做题过程中相对来说花了较多时间的题目会进行单独的题解,而对于较简单的会进行多题放在一篇博客中,希望这些总结能够帮助到大家,预祝大家在pat比赛中取得好成绩

Queueing at Bank (25分)

Suppose a bank has K windows open for service. There is a yellow line in front of the windows which devides the waiting area into two parts. All the customers have to wait in line behind the yellow line, until it is his/her turn to be served and there is a window available. It is assumed that no window can be occupied by a single customer for more than 1 hour.

Now given the arriving time T and the processing time P of each customer, you are supposed to tell the average waiting time of all the customers.

Input Specification:
Each input file contains one test case. For each case, the first line contains 2 numbers: N (≤10​^4) - the total number of customers, and K (≤100) - the number of windows. Then N lines follow, each contains 2 times: HH:MM:SS - the arriving time, and P - the processing time in minutes of a customer. Here HH is in the range [00, 23], MM and SS are both in [00, 59]. It is assumed that no two customers arrives at the same time.

Notice that the bank opens from 08:00 to 17:00. Anyone arrives early will have to wait in line till 08:00, and anyone comes too late (at or after 17:00:01) will not be served nor counted into the average.

Output Specification:
For each test case, print in one line the average waiting time of all the customers, in minutes and accurate up to 1 decimal place.
Sample Input:

7 3
07:55:00 16
17:00:01 2
07:59:59 15
08:01:00 60
08:00:00 30
08:00:02 2
08:03:00 10

Sample Output:

8.2

中文题目

假设一家银行有 K 个服务窗口。 窗户前面有一条黄线,将等候区分为两部分。 所有客户都必须在黄线后面排队等候,直到轮到他/她服务并且有可用的窗口为止。 假定一个窗口不能被单个客户占用超过 1 小时,即如果某位顾客的业务已经办理了一小时,则立即终止此项业务。 现在给定每个客户的到达时间 T 和业务办理时间 P,请计算所有客户的平均等待时间。 输入格式 第一行包含两个整数 N 和 K,分别表示客户数量以及窗口数量。 接下来 N 行,每行包含两个时间,分别是一个客户的到达时间,用 HH:MM:SS 表示,以及一个客户的业务办理时间 P(单位:分钟)。 HH 在 [00,23] 范围内,MM 和 SS 都在 [00,59] 范围内。 所有客户的到达时间均不相同。 请注意,银行的营业时间为 08:00 至 17:00。 任何人提前到达都必须排队等候至 08:00,而任何人来得太晚(在 17:00:01 或之后到达)都将不被服务也无需计入平均值。 注意只要客户在17:00之前排上队,则即使办理业务时超过17:00,也会被服务。 输出格式 输出平均等待时间(单位:分钟),结果保留一位小数。 注意,从到达银行至开始办理业务这一期间视为等待期间。

数据的存储

分析:这题是到模拟题在pat甲级里算是比较复杂的题目了,对于我在做这一题的过程中首先遇到的难点是我应该用什么东西来存窗口以及人物的信息后面经过一些思考还有老师的讲解终于知道了(*^_^*)

首先我们要知道对于人来说我们只需要用到到达时间以及服务时间,而对于窗口来说我们只要知道窗口可以开始服务的时间所以:

  • 我们用一个结构体来存储人的信息;
struct Person{
	//计算到凌晨0:0分的秒数
	int arrive_time;
	int serve_time;//服务也是秒数
	
	//重载一个比较运算符用于排序
	bool operator<(const Person& t) {
		return arrive_time < t.arrive_time;
	}
}persons[N];
  • 对于窗口来说我们只要用一个优先队列来存储就好了
priority_queue<int, vector<int>, greater<int>>windows;
	//初始化为8点
	for (int i = 0; i < m; i++) {
		windows.push(8 * 3600);//初始化m个窗口
	}

代码逻辑分析

1、首先我们把人到达的时间全部放到结构体数组中再进行排序(以到达时间进行排序)
2、初始化窗口
3、窗口要对用户进行服务时有两种情况:

 - 用户一来可能就有空余的窗口了
 - 用户来的时候没有窗口,用户等了一段时间
 
4、更新窗口信息:开始服务的时间+该用户需要服务的时间(queue不支持修改所以我们就先删除然后再进行插入就好)
5、对于用户17点以后到的全部不予服务

注意

在这我们的到达时间和服务时间都是以秒为单位(到达时间:到达时间到改天0:0分经过的秒数)当最后计算答案时我们再统一变成秒


代码实现

//1071
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int N = 10010, M = 110;

int n, m;

struct Person{
	//计算到凌晨0:0分的秒数
	int arrive_time;
	int serve_time;  //服务时间也是改成秒数
	bool operator<(const Person& t) {	//按到达时间进行排序 
		return arrive_time < t.arrive_time;
	}
}persons[N];
/*
7 3
07:55:00 16
17:00:01 2
07:59:59 15
08:01:00 60
08:00:00 30
08:00:02 2
08:03:00 10
*/
int main() {
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		int hour, minute, second, serve_time;
		//格式化输入
		scanf("%d:%d:%d %d", &hour, &minute, &second, &serve_time);
		serve_time = min(serve_time, 60);
		persons[i] = { hour * 3600 + minute * 60 + second,serve_time*60 };
	}
	priority_queue<int, vector<int>, greater<int>>windows;
	sort(persons, persons + n);

	for (int i = 0; i < m; i++) {
		windows.push(8 * 3600);//初始化m个窗口
	}
	
	int cnt = 0;
	double sum = 0;
	for (int i=0;i<n;i++) {
		auto person=persons[i];
		auto w = windows.top();
		windows.pop();
		//用户来的时间太晚了,直接break 
		if (person.arrive_time > 17 * 3600)break;
		int start_serve_time = max(person.arrive_time, w);//顾客可能是一来就有了,或者是要等
		sum += start_serve_time - person.arrive_time;  // 等待时间:开始服务时间-到达时间
		windows.push(start_serve_time + person.serve_time);
		cnt++;
	}
	
	printf("%.1lf\n", (double)sum / cnt / 60);
	return 0;
}

代码运行结果

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值