PTA甲级考试真题练习14——1014 Waiting in Line

题目:
在这里插入图片描述

生词生句

  1. The first N customers are assumed to be served at 8:00am.
    前N个顾客假设8点到达

思路

比较复杂的模拟题,不过模拟题主要是注意细节以及一些坑就还好
具体实现:模拟事件机制,分别有到达事件和从某窗口离开事件,然后构造事件队列,首先初始化事件队列,将到达的顾客构造到达事件送入事件队列,然后处理事件队列(事件队列中应按照发生时间较小的优先),并且在到达事件中构造离开事件并加入事件队列,直到所有事件队列处理完毕

坑点

  1. 不是17:00之后就停止服务,而是17:00后(包括17:00,下同)不允许开始服务了,所以在17:00之前开始服务就算超过17:00也要服务下去。
    注意:在某个事件发生的时候超过了17:00,将所在窗口的剩余队列清空并且将等待队列也要清空!!!
  2. 注意队列容量为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);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值