数据结构_习题8.1 银行排队问题之单队列多窗口服务_习题8.2 银行排队问题之单队列多窗口加VIP服务_习题8.3 银行排队问题之单窗口“夹塞”版
- 利用clockCnt++,进行时钟打点前进,每到一个点便处理相应的事;
- 在数据结构上,利用vector与int front模拟队列(这样可以用下标访问该模拟队列,进行综合操作);
- 这种类型的调试,建议在过程中添加输出cout,检查每一步状况;
- 以下代码有注释,8.3注的比较好。
/* 8.1 */
#include <iostream>
#include <stdlib.h>
using namespace std;
typedef struct customer{
int in; //进入时间
int need; //需要的时间
} CUS;
typedef CUS *cp;
typedef struct window{
int cnt; //统计服务过的顾客数目
int work; //当前尚需的工作时间,0代表可以接待顾客
} WIN;
typedef WIN *wp;
int n, m;
int clockCnt = -1, tolWait = 0, maxWait = 0;
cp C[1000];
wp W[10];
void inputDeal(void);
void outputDeal(void);
int main()
{
inputDeal();
int ci=0, remainWork;
while (true)
{
clockCnt++;
remainWork=0;//该时间工作后是否还有剩余工作
for (int i = 0; i < m; i++)
if(W[i]->work>0)
{
W[i]->work--;
remainWork+=W[i]->work;
}
if(remainWork==0 && ci==n) break;
for (int i = 0; i < m && ci!=n; i++) //防止ci==n时if越段
if(W[i]->work==0 && C[ci]->in<=clockCnt)//有空窗口,且有已到达顾客
{
int cWait=clockCnt - C[ci]->in; //该顾客等待情况
tolWait+=cWait;
if(cWait>maxWait) maxWait=cWait;
W[i]->cnt++;//窗口接待
W[i]->work=C[ci]->need;
ci++;//顾客已接待,指针后移
}
}
outputDeal();
return 0;
}
void inputDeal(void)
{
scanf("%d", &n);
for (int i = 0; i < n; i++) //初始化顾客情况
{
C[i] = (cp)malloc(sizeof(CUS));
scanf("%d %d", &C[i]->in, &C[i]->need);
if (C[i]->need > 60) C[i]->need = 60; //超过60的需求不接受
}
scanf("%d", &m);
for (int i = 0; i < m; i++) //初始化窗口
{
W[i] = (wp)malloc(sizeof(WIN));
W[i]->cnt = 0, W[i]->work = 0;
}
}
void outputDeal(void)
{
printf("%.1lf %d %d\n", (double)tolWait / n, maxWait, clockCnt);
for (int i = 0; i < m; i++)
printf("%d%c", W[i]->cnt, i == m - 1 ? '\n' : ' ');
}
/* 8.2 */
#include <iostream>
#include <stdlib.h>
using namespace std;
typedef struct customer
{
int in; //进入时间
int need; //需要的时间
int vip; // 1 vip;0 non;-1 used
} CUS;
typedef CUS *cp;
typedef struct window
{
int cnt; //统计服务过的顾客数目
int work; //当前尚需的工作时间,0代表可以接待顾客
} WIN;
typedef WIN *wp;
int n, m, mVip;
int clockCnt = -1, tolWait = 0, maxWait = 0;
cp C[1000];
wp W[10];
void inputDeal(void);
void outputDeal(void);
void cusToWin(int wi, int id);//顾客去窗口办事
int main()
{
inputDeal();
/*ci从0到n-1,越段问题必须注意!*/
int ci = 0,remainWork;
while (true)
{
clockCnt++;
remainWork = 0; //该时间工作后是否还有剩余工作
for (int i = 0; i < m; i++)
if (W[i]->work > 0)
{
W[i]->work--;
remainWork += W[i]->work;
}
if (remainWork == 0 && ci == n) break;
//处理顾客
if (W[mVip]->work == 0) //vip窗口没人
for (int i = ci; i<n && C[i]->in <= clockCnt ; i++)
if (C[i]->vip==1){ //从未处理的队首 到 已经到达的末尾,找vip
cusToWin(mVip,i);
break; //vip窗口有人了,跳出
}
for (int i = 0; i < m; i++)
{
while(ci!=n && C[ci]->vip==-1) ci++; //越过已被处理的顾客
//有空窗口,且有到达顾客
if (W[i]->work == 0 && ci!=n &&C[ci]->in <= clockCnt)
cusToWin(i,ci++);
}
}
outputDeal();
return 0;
}
void inputDeal(void)
{
scanf("%d", &n);
for (int i = 0; i < n; i++) //初始化顾客情况
{
C[i] = (cp)malloc(sizeof(CUS));
scanf("%d %d %d", &C[i]->in, &C[i]->need, &C[i]->vip);
if (C[i]->need > 60)
C[i]->need = 60; //超过60的需求不接受
}
scanf("%d %d", &m, &mVip);
for (int i = 0; i < m; i++) //初始化窗口
{
W[i] = (wp)malloc(sizeof(WIN));
W[i]->cnt = 0, W[i]->work = 0;
}
}
void outputDeal(void)
{
printf("%.1lf %d %d\n", (double)tolWait / n, maxWait, clockCnt);
for (int i = 0; i < m; i++)
printf("%d%c", W[i]->cnt, i == m - 1 ? '\n' : ' ');
}
void cusToWin(int wi, int id)
{
int cWait = clockCnt - C[id]->in; //该顾客等待情况
tolWait += cWait;
if (cWait > maxWait)
maxWait = cWait;
W[wi]->cnt++; //窗口接待
W[wi]->work = C[id]->need;
C[id]->vip=-1;
}
/* 8.3 */
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
typedef struct queueNode *np;
typedef struct queueNode
{
int in; //到达时间
int need; //处理时间
int group; //所属群体,-1表示无归属
bool getWindows;//是否上过机
string name; //谁
np help; //他要帮助的对象链表
} QN;
int clockCnt = -1, tolTime = 0;// 时钟打点,总等待时间
int n, m, ci = 0, front = 0; // C用ci访问,Q用front访问
vector<np> C; // 存用户数据
vector<np> Q; // 排队上机
unordered_map<string, int> M; // 他属于哪个群体
void inputProcess(void) //读输入
{
scanf("%d %d", &n, &m);
for (int i = 0, l; i < m; i++)
{
scanf("%d", &l);
for (int j = 0; j < l; j++)
{
string s;
cin >> s;
M[s] = i;
}
}
for (int i = 0; i < n; i++)
{
np tmp = new QN; //必须用new,malloc不认识c++的string类
cin >> tmp->name;
if(M.find(tmp->name)!=M.end()) //确定这个人有没有群体
tmp->group = M[tmp->name]; //直接执行该语句,若map中无该人数据,将赋予默认值
else tmp->group=-1; //-1表示无归属
tmp->help = NULL, tmp->getWindows = false;
scanf("%d %d", &tmp->in, &tmp->need);
if(tmp->need>60) tmp->need=60; //超过60按60算
C.push_back(tmp);
}
}
void inQueue(np tmp);
void updateQ(np tmp);
int main()
{
inputProcess();
while (ci < n || front != Q.size()) //用户数据没有处理完,或者队列尚有未处理用户
{
if (front != Q.size()) //队列有用户(包含了上机和排队的两种)
updateQ(Q[front]); //处理队列情况,即运行1个单位时
clockCnt++; //当前时间,从0开始
while (ci < n && C[ci]->in == clockCnt)
inQueue(C[ci++]); //正确的时刻,上正确的机
}
printf("%.1lf", (double)tolTime / n);
return 0;
}
void inQueue(np tmp)
{
int findG = tmp->group, flag = 1; //flag默认前面没有同群体的人
if(findG!=-1)
{
for (int i = front; i < Q.size(); i++)
if (Q[i]->group == findG)
{ //找到了所属群体
np hp = Q[i];
while (hp->help != NULL)
hp = hp->help; //插help链表
hp->help = tmp;
flag = 0;
break;
}
}
if (flag) Q.push_back(tmp); //默认情况,好好排队。
}
void updateQ(np tmp)
{ //已上机&&处理完了,->找到需要帮助的
while (tmp->getWindows==true && tmp->need==0 && tmp->help!=NULL)
tmp=tmp->help;
//需要帮助的人,也已上机&&处理完了,Q中还有在排队的
if(tmp->getWindows==true && tmp->need==0 && ++front != Q.size())
updateQ(Q[front]); //让队中下一位上机。
else
{
if(tmp->getWindows==false) //没有上过机
{
tolTime+=clockCnt-tmp->in; //等了多久
tmp->getWindows=true; //让你上机
cout<<tmp->name<<endl; //光荣输出
}
tmp->need--; //在机子上的,运行1单位时
}
}
标签:
数据结构
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通