题目:
生词生句
- The first N customers are assumed to be served at 8:00am.
前N个顾客假设8点到达
思路
比较复杂的模拟题,不过模拟题主要是注意细节以及一些坑就还好
具体实现:模拟事件机制,分别有到达事件和从某窗口离开事件,然后构造事件队列,首先初始化事件队列,将到达的顾客构造到达事件送入事件队列,然后处理事件队列(事件队列中应按照发生时间较小的优先),并且在到达事件中构造离开事件并加入事件队列,直到所有事件队列处理完毕
坑点
- 不是17:00之后就停止服务,而是17:00后(包括17:00,下同)不允许开始服务了,所以在17:00之前开始服务就算超过17:00也要服务下去。
注意:在某个事件发生的时候超过了17:00,将所在窗口的剩余队列清空并且将等待队列也要清空!!! - 注意队列容量为1的情况!这时候等待队列不仅要进一个到窗口队列中,并且要构造离开事件!!!
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<string>
#include<unordered_set>
#include<map>
#include<vector>
#include<queue>
#include<set>
#include<list>
using namespace std;
#define nmax 1005
void OpenForDay();
void CustomerArrived();
void CustomerDepature();
//事件结构体
typedef struct MyEvent
{
int OccurTime; //时间发生时刻
int NType; // 事件类型,0表示到达事件,1至n表示n个窗口的离开事件
int ID; // 触发事件用户ID
int Duration; // 办理事务所需时间
}MyEvent;
//队列的数据元素类型
typedef struct
{
int ArrivalTime; //到达时刻
int Duration; //办理事务所需时间
int ID;
}QElemType;
//程序中用到的主要变量
list<MyEvent> ev; //事件队列
MyEvent en; //事件
vector<queue<QElemType>> vec; //存放n个客户队列
QElemType customer; //客户记录
queue<QElemType> wait; //等待队列
int departTime[nmax]; //记录客户离开事件
int windows_num; //窗口数
int line_capacity; //窗口容量
int people_num; //客户数
int ask_num; //询问数
void Bank_Simulation(int CloseTime)
{
//初始化
OpenForDay();
while (!ev.empty())
{
auto iter = ev.rbegin();
en = *iter;
ev.pop_back();
if(en.NType == 0)
CustomerArrived();
else
CustomerDepature();
}
for (int i = 0; i < ask_num; ++i)
{
int ask_i;
cin >> ask_i;
int time = departTime[ask_i];
if (time != 9999)
{
int hour = time / 60;
time = time % 60;
printf("%.2d:%.2d\n", hour, time);
}
else
{
cout << "Sorry" << endl;
}
}
}
void InsertList(const MyEvent& env)
{
if (ev.empty())
{
ev.emplace_back(env);
return;
}
for (auto iter = ev.begin(); iter != ev.end(); ++iter)
{
if (env.OccurTime >= iter->OccurTime)
{
ev.insert(iter,env);
return;
}
}
ev.emplace_back(env);
}
void OpenForDay()
{
//初始化事件队列
for (int i = 1; i <= people_num; ++i)
{
en.ID = i;
en.OccurTime = 480;
en.NType = 0;
cin >> en.Duration;
InsertList(en);
}
//初始化n个客户队列
for (int i = 1; i <= windows_num; ++i)
{
queue<QElemType> q;
vec.push_back(q);
}
}
void CustomerArrived()
{
//构造顾客信息
customer.ArrivalTime = en.OccurTime;
customer.Duration = en.Duration;
customer.ID = en.ID;
//如果有空闲的位置
for (int i = 0; i < vec.size(); ++i)
{
if (vec[i].empty())
{
//插入进队列,开始处理
vec[i].push(customer);
//添加用户离开事件
MyEvent depart;
depart.ID = customer.ID;
depart.NType = i+1;
depart.OccurTime = customer.ArrivalTime + customer.Duration;
InsertList(depart);
return;
}
}
//如果没有空闲位置但是有黄线内的位置
int minlen_index = -1;
int minlen = 99999;
for (int i = 0; i < vec.size(); ++i)
{
if (vec[i].size() < line_capacity)
{
if (vec[i].size() < minlen)
{
minlen = vec[i].size();
minlen_index = i;
}
}
}
if (minlen != 99999)
{
vec[minlen_index].push(customer);
}
else
{
//如果没有位置进等待队列
wait.push(customer);
}
}
void CustomerDepature()
{
//处理客户离开事件
int i = en.NType-1;
departTime[en.ID] = en.OccurTime;
vec[i].pop();
//如果离开后队列中还有元素
if (!vec[i].empty())
{
customer = vec[i].front();
//添加用户离开事件
MyEvent depart;
depart.ID = customer.ID;
depart.NType = i + 1;
if (en.OccurTime >= 1020)
{
while (!vec[i].empty())
{
int ID = vec[i].front().ID;
departTime[ID] = 9999;
vec[i].pop();
}
while (!wait.empty())
{
int ID = wait.front().ID;
departTime[ID] = 9999;
wait.pop();
}
return;
}
depart.OccurTime = en.OccurTime + customer.Duration;
InsertList(depart);
}
//如果离开后队列中元素个数为容量-1
if (vec[i].size() == line_capacity - 1 && !wait.empty())
{
if (en.OccurTime >= 1020)
{
while (!wait.empty())
{
int ID = wait.front().ID;
departTime[ID] = 9999;
wait.pop();
}
return;
}
customer = wait.front();
wait.pop();
int minlen_index = -1;
int minlen = 99999;
for (int i = 0; i < vec.size(); ++i)
{
if (vec[i].size() < line_capacity)
{
if (vec[i].size() < minlen)
{
minlen = vec[i].size();
minlen_index = i;
}
}
}
vec[minlen_index].push(customer);
//如果line_capacity==1,这时不仅要进入等待序列,还要开始服务
if (vec[minlen_index].size() == 1)
{
MyEvent depart;
depart.ID = customer.ID;
depart.NType = minlen_index + 1;
depart.OccurTime = en.OccurTime + customer.Duration;
InsertList(depart);
}
}
}
int main()
{
cin >> windows_num >> line_capacity >> people_num >> ask_num;
Bank_Simulation(1020);
}