题目介绍
题目链接
https://pintia.cn/problem-sets/994805342720868352/problems/994805498207911936
题目考点
队列和模拟,重难点在于模拟而非队列
题目难度
PAT甲级30分
题目大意
- 有N个窗口,每个窗口最多允许M个人站在黄线前排队,剩下的客户在黄线外等候。
- 客户进入黄线时会选择人数最少的窗口排队,如果有重复,就选择索引最小的窗口
- 客户$C_i$办理业务需要$T_i$分钟。
- 前N个客户在8:00开始服务。
- 请计算某个客户结束服务的时间。
输入
- N:正整数,不超过20,服务窗口的数量
- M:正整数,不超过10,每个服务窗口前最多有几个人等待
- K:正整数,不超过1000,顾客的数量,顾客索引为[1,K]
- Q:要查询的顾客服务完成时间的数量
- K个正整数:每个顾客完成服务需要几分钟
- Q个正整数:需要查询的Q个顾客
输出
按
HH:MM
的格式输出Q个顾客完成服务的时间,如果在17:00之前还没有开始服务,则输出Sorry。
题解
解题思路
题目中有一个信息并没有十分明确地表达出来:黄线外的客户进入黄线以内时,索引小的人优先。根据这一点,所以从1到K遍历客户就可以。
整体思路:计算出所有客户完成服务的时间,最后进行Q个查询并根据分钟数输出完成服务的时间(或sorry)
如何计算出所有客户完成服务的时间?其实是个模拟题,核心在于入队,入队分2个阶段。
为什么核心是入队?某客户完成服务的时间取决于它前面1个客户完成服务的时间。而在某客户入队时,该客户前面就是队尾客户,所以该客户完成服务的时间=队尾客户完成服务的时间+该客户的服务时长。如果入队时队伍是空的,那该客户完成服务的时间就等于其服务所需时长。
入队第1阶段是前N×M个客户入队
无需等待黄线,只需按照客户索引顺序依次入队,其中前N个客户是在8:00开始服务。
如何让这些客户正确地排队呢?用2层循环。内循环:在n个窗口中选择窗口(从1到N)入队。外循环:使内循环重复m次达到n×m的效果。这样就实现了“选择人数最少、索引最小的窗口”的要求。
在客户入队时,我们需要不断更新客户索引,所以当已经没有客户时(即客户索引超过K时)要停止入队;另外所有窗口排满时也要停止入队,这通过双循环的判断条件实现。
入队第2阶段是剩下的客户入队
假如还有剩下的客户(即客户索引还未超过K时),那就要找出队伍最短的窗口,让下一个客户入队。
如何找到队伍最短的窗口呢?在该方法中,并不是通过比较n个窗口的排队长度。因为如果还剩有客户就说明每个窗口都是满的,那队伍最短就没有意义了。而最快有客户结束服务的窗口(如果有重复,就选索引最小的窗口)就是队伍最短的窗口,也就是找到哪个窗口队首客户完成服务的时间最早。
其它
关于题目
好久没做题目了,脑子和手都很生疏。看到这道题,我就想起来数学建模里做过的题、排队论什么的。思路很乱,我很自闭,这份题解的核心在于抓住了入队的规律。如果是更复杂的排队论问题,也许就需要模拟,模拟出一个时钟,然后某一分钟遍历所有窗口?这种思路确实可以,但效率不高。
关于算法题
脱离这道题来讲,模拟题(可能大多数算法题也是)都是找规律,然后用规律去求结果。
1 | // Problem: PAT Advanced 1014 |
参考链接
Github(github.com):@chouxianyu
Github Pages(github.io):@臭咸鱼
知乎(zhihu.com):@臭咸鱼
博客园(cnblogs.com):@臭咸鱼
B站(bilibili.com):@绝版臭咸鱼
微信公众号:@臭咸鱼
转载请注明出处,欢迎讨论和交流!