编程基础 - 队列实例 - 售票排队问题 (Queue Ticketing)
文章目录
1 售票排队问题简述 (Introduction)
售票排队问题可以扩展成任意现实生活中的排队问题,例如:
-
购买火车票
-
医院、银行等取号排队
这些排队者主要重复以下过程:
- (1)消费者到达取号机取号,加入叫号队列,等待叫号;
- (2)窗口没有消费者时,进行叫号,然后服务该消费者。
其实都是同一种问题。我们接下来以实例来说明。
2 经典窗口排队问题 (Ticketing Problem)
-
背景描述:
- (1)所有顾客只能排一队,即只有一个队列;
- (2)服务窗口为每位顾客平均服务时间为180秒;
- (3)服务窗口有多个;
- (4)某个窗口空闲,则顾客不需排队,若全部不空闲,则排队;
- (5)每隔15秒就进入一个顾客;
-
问题:
根据每隔顾客的平均服务时间来求得开多少个窗口最合适? -
提示:
总服务时间除以顾客数量,越小越好。 -
解答:
在解释这个问题时,我们需要考虑两种情况:- 顾客数量比窗口数量少,则最适合的窗口数量就是顾客数量;
- 顾客数量比窗口数量多,或正好相等,则:
不难看出,当每个窗口都有顾客时,下一个顾客进店时间和第一个窗口结束服务时间相等,则窗口数量是最适合的。
即,最适合窗口数量 = (平均服务时间 / 顾客进店时间间隔)向上取整。- 如果适合的窗口数量比最大窗口数量小,则直接得到适合的窗口数量;
- 如果适合的窗口数量比最大窗口数量大或相等,则结果就是最大窗口数量。
上述解答只是说明了,打开多少窗口是最适合的,且没有得到所有顾客的平均服务时间,所以我们可以拿它来验证程序结果是否正确。
现在,我们开始用队列来计算它们。
3 C++完整代码 (C++ Code)
// Ticketing Problem
// Author: https://blog.csdn.net/DarkRabbit
#include <string> // 字符串
#include <vector> // 向量列表
#include <queue> // 队列
#include <map> // 有序字典,用于存储每一步计算结果
#include <iostream>
using namespace std;
constexpr int CUSTOMER_ENTER_INTERVAL = 15; // 顾客进店时间间隔
constexpr int SERVICE_TIME_PER_CUSTOMER = 180; // 每名顾客服务时间
// 顾客时间
struct CustomerTime
{
int enter; // 进店时间
int leave; // 离开时间
int GetSpend() // 进店到离开的时间间隔
{
return leave - enter;
}
};
// cin输入
// params:
// customerCount: 顾客数量
// windowMaxCount: 窗口最大数量
void Input(int& customerCount, int& windowMaxCount)
{
cout << "按次序输入顾客数量,最大窗口数量:" << endl;
while (!(cin >> customerCount >> windowMaxCount)
|| customerCount < 1 || windowMaxCount < 1)
{
cin.clear();
cin.