做一下倒数两题,都是在队列模拟的程序基础上做点修改测试。

5.找出平均等候时间为1分钟时,每小时到达的客户数为多少(试验时间不少于100小时)。

指定队伍最大长度10人,模拟100小时。粗略估计答案在10到20之间,所以我在开始输入的时候为其生成10到20之间的随机数,通过循环不断去试,直到模拟完的平均等待时间等于1分钟为止。

//Bank.cpp -- Using Class

#include "Queue.h"
#include <iostream>
#include <ctime> //for time() const int MIN_PER_HR = 60; bool newcustomer(double x); int main()
{
using std::cin;
using std::cout;
using std::endl;
using std::ios_base; std::srand(std::time(0)); //生成随机数时间种子 int flag = 1; //用于保持循环
cout<<"Case Study: Bank of Heather Automatic Teller\n"; cout<<"Enter maximum size of queue: ";
int qs;
cin>>qs; //指定排队的最大人数,不指定默认为10
Queue line(qs); //初始化Queue类对象line cout<<"Enter the number of simulation hours: ";
int hours;
cin>>hours; //指定想要模拟的小时数 long cyclelimit = MIN_PER_HR * hours; //将小时转化为分钟,因为后面每分钟为一个循环周期
while(flag)
{
cout<<"Enter the average number of customers per hour: ";
double perhour; cout<<"(Generated)";
perhour = rand()%20 + 10; //在10到20之间随机试 //cin>>perhour; //指定一小时平均有多少顾客
double min_per_cust;
min_per_cust = MIN_PER_HR / perhour; //换算平均下来每多少分钟到达一位顾客 Item temp; //一个临时顾客对象,用于代表每个循坏周期服务的顾客
long turnaways = 0;
long customers = 0;
long served = 0;
long sum_line = 0;
int wait_time = 0;
long line_wait = 0; //开始模拟
for(int cycle = 0;cycle < cyclelimit;cycle++)
{
if(newcustomer(min_per_cust))
{
if(line.isfull())
turnaways ++; //因为队伍已满而离去的人+1
else
{
customers ++; //到达的顾客数+1
temp.set(cycle); //为这位顾客生成随机的服务时间(1-3分钟),并记录其到达的时间
line.enqueue(temp); //顾客入队,更新内部所有指针
}
} /* wait_time是每位顾客服务时间的计数器,可以这么想象:*/
/* 每有一位顾客到达了队首,就开始掐表倒计时(1-3分钟随机)*/
/* 时间一到0,表示服务完毕,下一个人补上,重新倒计时,如此重复 */
if(wait_time <=0 && !line.isempty()) //上一位服务完毕且队伍里还有人
{
line.dequeue(temp); //下一位出队,开始服务
wait_time = temp.ptime(); //置计数器为该位顾客的服务时间
line_wait += cycle - temp.when(); //用现在的时间减去该顾客的到达时间,所有结果累加(即总等待时间)
served ++; //已服务的人数+1
}
if(wait_time>0)
wait_time--; //上一位服务未完毕,保持当前状态,时间-1
sum_line += line.queuecount(); //数一下现在队伍有多少人,把每一分钟的结果都累加起来
} //报告结果
if(customers > 0)
{
cout<<"customers accepted: "<<customers<<endl; //总到来的顾客数
cout<<" customers served: "<<served<<endl; //总服务的顾客数
cout<<" turnaways: "<<turnaways<<endl; //总离去的顾客数(到来却因队伍满了而离去)
cout<<"average queue size: ";
cout.precision(2); //设定输出的有效数字为两位
cout.setf(ios_base::fixed,ios_base::floatfield); //输出浮点数为定点模式,结合上句的效果就是输出到小数点后两位
cout<<(double)sum_line/cyclelimit<<endl; //平均每分钟的排队人数
cout<<" average wait time: "<<(double)line_wait/served<<" minutes\n"; //平均每个人的等待时间
}
else
cout<<"No customers!\n";
cout<<"Done!\n"; if((double)line_wait/served == 1)
{
flag = 0;
cout<<"the average number of customers per hour: "<<perhour<<endl;
}
//cout<<"Enter 1 to simulate again,0 to quit: ";
//cin>>flag; //输入0以终止循环
} return 0;
} /* 判断顾客是否到达的函数 */
/* RAND_MAX是能够生成的最大随机数,rand()会生成[0,RAND_MAX)之间的随机数 */
/* 因此rand()/RAND_MAX会生成[0,1)之间的随机数,再乘以x就是[0,x)之间的随机数 */
/* 加上小于1的判断,生成的数会有1/x的概率小于1,而小于1就表示这一分钟内有顾客到了 */
bool newcustomer(double x)
{
return (std::rand() * x/RAND_MAX < 1);
}

此种情况下,最后计算的结果为18人。

6.再开一台ATM,新来的顾客会根据人数拍队,模拟新的情况,再次找出平均等待时间为1分钟,每小时到达的客户数应为多少。

设定每队最大能容纳5人,模拟200小时。平均每小时到达人数从50开始一个个试。

如果某一队人比另一队少的话,新来的顾客就会去那一队。如果两队人一样多,就随便选一个(随机数)。

//Bank.cpp -- Using Class

#include "Queue.h"
#include <iostream>
#include <ctime> //for time() const int MIN_PER_HR = 60; bool newcustomer(double x); int main()
{
using std::cin;
using std::cout;
using std::endl;
using std::ios_base; std::srand(std::time(0)); //生成随机数时间种子 int flag = 1; //用于保持循环
cout<<"Case Study: Bank of Heather Automatic Teller\n"; cout<<"Enter maximum size of queue: ";
int qs;
cin>>qs; //指定排队的最大人数,不指定默认为10
Queue line(qs); //初始化Queue类对象line
Queue line2(qs); cout<<"Enter the number of simulation hours: ";
int hours;
cin>>hours; //指定想要模拟的小时数 long cyclelimit = MIN_PER_HR * hours; //将小时转化为分钟,因为后面每分钟为一个循环周期 Item temp1; //一个临时顾客对象,用于代表每个循坏周期服务的顾客
Item temp2;
while(flag)
{
cout<<"Enter the average number of customers per hour: ";
double perhour;
cin>>perhour; //指定一小时平均有多少顾客
double min_per_cust;
min_per_cust = MIN_PER_HR / perhour; //换算平均下来每多少分钟到达一位顾客 long turnaways = 0;
long customers = 0;
long served = 0;
long sum_line_1 = 0;
long sum_line_2 = 0;
int wait_time_1 = 0;
int wait_time_2 = 0;
long line_wait_1 = 0;
long line_wait_2 = 0;
//开始模拟
for(int cycle = 0;cycle < cyclelimit;cycle++)
{
if(newcustomer(min_per_cust))
{
if(line.isfull()&&line2.isfull())
turnaways ++; //因为队伍已满而离去的人+1
else
{
customers ++; //到达的顾客数+1
if(line.queuecount() < line2.queuecount())
{
temp1.set(cycle); //为这位顾客生成随机的服务时间(1-3分钟),并记录其到达的时间
line.enqueue(temp1);
}
else if(line.queuecount() > line2.queuecount())
{
temp2.set(cycle); //为这位顾客生成随机的服务时间(1-3分钟),并记录其到达的时间
line2.enqueue(temp2);
}
else
{
int choice = rand()%2;
if(choice<1)
{
temp1.set(cycle);
line.enqueue(temp1);
}
else
{
temp2.set(cycle);
line2.enqueue(temp2);
}
}
}
} /* wait_time是每位顾客服务时间的计数器,可以这么想象:*/
/* 每有一位顾客到达了队首,就开始掐表倒计时(1-3分钟随机)*/
/* 时间一到0,表示服务完毕,下一个人补上,重新倒计时,如此重复 */
if(wait_time_1 <=0 && !line.isempty()) //上一位服务完毕且队伍里还有人
{
line.dequeue(temp1); //下一位出队,开始服务
wait_time_1 = temp1.ptime(); //置计数器为该位顾客的服务时间
line_wait_1 += cycle - temp1.when(); //用现在的时间减去该顾客的到达时间,所有结果累加(即总等待时间)
served ++; //已服务的人数+1
}
if(wait_time_2 <=0 && !line2.isempty())
{
line2.dequeue(temp2); //下一位出队,开始服务
wait_time_2 = temp2.ptime(); //置计数器为该位顾客的服务时间
line_wait_2 += cycle - temp2.when(); //用现在的时间减去该顾客的到达时间,所有结果累加(即总等待时间)
served ++; //已服务的人数+1
} if(wait_time_1>0)
wait_time_1--; //上一位服务未完毕,保持当前状态,时间-1
if(wait_time_2>0)
wait_time_2--;
sum_line_1 += line.queuecount(); //数一下现在队伍有多少人,把每一分钟的结果都累加起来
sum_line_2 += line2.queuecount();
} //报告结果
if(customers > 0)
{
cout<<"customers accepted: "<<customers<<endl; //总到来的顾客数
cout<<" customers served: "<<served<<endl; //总服务的顾客数
cout<<" turnaways: "<<turnaways<<endl; //总离去的顾客数(到来却因队伍满了而离去)
cout<<"average queue size:(1) ";
cout.precision(2); //设定输出的有效数字为两位
cout.setf(ios_base::fixed,ios_base::floatfield); //输出浮点数为定点模式,结合上句的效果就是输出到小数点后两位
cout<<(double)sum_line_1/cyclelimit<<endl; //1平均每分钟的排队人数
cout<<"average queue size:(2) ";
cout<<(double)sum_line_2/cyclelimit<<endl; //2平均每分钟的排队人数
cout<<" average wait time: "<<(double)(line_wait_1+line_wait_2)/served<<" minutes\n"; //平均每个人的等待时间
}
else
cout<<"No customers!\n";
cout<<"Done!\n"; cout<<"Enter 1 to simulate again,0 to quit: ";
cin>>flag; //输入0以终止循环
} return 0;
} /* 判断顾客是否到达的函数 */
/* RAND_MAX是能够生成的最大随机数,rand()会生成[0,RAND_MAX)之间的随机数 */
/* 因此rand()/RAND_MAX会生成[0,1)之间的随机数,再乘以x就是[0,x)之间的随机数 */
/* 加上小于1的判断,生成的数会有1/x的概率小于1,而小于1就表示这一分钟内有顾客到了 */
bool newcustomer(double x)
{
return (std::rand() * x/RAND_MAX < 1);
}

模拟结果:

可以看出大约平均每小时到达51或52个顾客,等待时间会保持在1分钟。但是,我翻来覆去地看代码,也不知道为什么平均等待时间会算出负数来,总觉得哪里有问题。

《C++primerplus》第12章练习题的更多相关文章

  1. JS读书心得:《JavaScript框架设计》——第12章 异步处理

    一.何为异步   执行任务的过程可以被分为发起和执行两个部分. 同步执行模式:任务发起后必须等待直到任务执行完成并返回结果后,才会执行下一个任务. 异步执行模式:任务发起后不等待任务执行完成,而是马上 ...

  2. ASM:《X86汇编语言-从实模式到保护模式》第12章:存储器的保护

    12章其实是11章的拓展,代码基本不变,就是在保护模式下展开讨论. ★PART1:存储器的保护机制 1. 修改段寄存器的保护 当执行把段选择子传到段寄存器的选择器部分的时候,处理器固件在完成传送之前, ...

  3. 敏捷软件开发:原则、模式与实践——第12章 ISP:接口隔离原则

    第12章 ISP:接口隔离原则 不应该强迫客户程序依赖并未使用的方法. 这个原则用来处理“胖”接口所存在的缺点.如果类的接口不是内敛的,就表示该类具有“胖”接口.换句话说,类的“胖”接口可以分解成多组 ...

  4. Linux就这个范儿 第12章 一个网络一个世界

    Linux就这个范儿 第12章 一个网络一个世界 与Linux有缘相识还得从一项开发任务说起.十八年前,我在Nucleus  OS上开发无线网桥AP,需要加入STP生成树协议(SpanningTree ...

  5. 阅读<构建之法>第三10、11、12章

    第10章:典型用户和场景 阅读了第10章之后,我知道典型用户很重要,典型用户是某类群体的代表,他们的观点能够反映一类人的观点与对产品的要求,那么要怎么样才能够从一类群体里,选择正确的典型用户反映我们研 ...

  6. CSS3秘笈第三版涵盖HTML5学习笔记9~12章

    第9章,装饰网站导航 限制访问,处于隐私方面考虑,浏览器已经开始限制可以对伪类:visited应用哪些CSS属性了.其中包括对已访问过的链接定义color.background-color.borde ...

  7. Android开发艺术探索》读书笔记 (12) 第12章 Bitmap的加载和Cache

    第12章 Bitmap的加载和Cache 12.1 Bitmap的高速加载 (1)Bitmap是如何加载的?BitmapFactory类提供了四类方法:decodeFile.decodeResourc ...

  8. 第12章 代理模式(Proxy Pattern)

    原文   第12章 代理模式(Proxy Pattern) 代理模式 概述: 在软件系统中,有些对象有时候由于跨越网络或者其他的障碍,而不能够或者不想直接访问另一个对象,如果直接访问会给系统带来不必要 ...

  9. 【机器学习实战】第12章 使用FP-growth算法来高效发现频繁项集

    第12章 使用FP-growth算法来高效发现频繁项集 前言 在 第11章 时我们已经介绍了用 Apriori 算法发现 频繁项集 与 关联规则.本章将继续关注发现 频繁项集 这一任务,并使用 FP- ...

随机推荐

  1. Python | 详解Python中的协程,为什么说它的底层是生成器?

    今天是Python专题的第26篇文章,我们来聊聊Python当中的协程. 我们曾经在golang关于goroutine的文章当中简单介绍过协程的概念,我们再来简单review一下.协程又称为是微线程, ...

  2. C# 自定义无边框窗体阴影效果

    工作中我们会经常遇到自定义一些窗口的样式,设置无边框然后自定义关闭.最大化等其他菜单,但是这样就失去了Winform自带的边框阴影效果,下面这个方法能让无边框增加阴影效果.代码如下: using Sy ...

  3. POJ-1273Drainage Ditches(网络流入门题,最大流)

    Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This ...

  4. Codeforces 1337D Xenia and Colorful Gems

    题意 给你3个数组\(a, b\)和\(c\),最小化\((x-y)^2+(y-z)^2+(z-x)^2\),其中\(x \in a, y \in b, z \in c\). 解题思路 这题其实第一眼 ...

  5. Linux 用户与权限

    这些天一直在看Linux的命令但是却没有写文章,因为感觉没有必要,哪些简单的命令,vi cat cd 啥的,是个做开发的就知道,所以就没写; 用户管理 第一个我们知道的用户就是Root 没错哦,这就是 ...

  6. Dockerfile使用,示例

    1.dockerfile介绍 镜像分类: 基础镜像:例如centos.Ubuntu.alpine 环境镜像:例如Java.php.go 项目镜像:将项目与环境镜像打包一起 2.Dockerfile常用 ...

  7. String的intern方法的使用场景

    在讲intern方法前,我们先简单回顾下Java中常量池的分类. 常量池的分类 Java中常量池可以分为Class常量池.运行时常量池和字符串常量池. 1. Class文件常量池 在Class文件中除 ...

  8. C#开发PACS医学影像处理系统(十五):Dicom影像交叉定位线算法

    1.定位线概念:某个方位的影像在另一个方向的影像上的投影相交线,例如横断面(从头到脚的方向)在矢状面(从左手到右手)上的影像投影面交线. 举个例子:右边的是MR(核磁共振)的某一帧切片,这是从头开始扫 ...

  9. Docker部署ElasticSearch以及使用

    ElasticSearch笔记 1. ElasticSearch前期 1.1 聊聊ElasticSearch的简介 ​ Elaticsearch,简称为es, es是一个开源的高扩展的分布式全文检索引 ...

  10. openstack核心组件——nova计算服务(7)

    云计算openstack核心组件——nova计算服务(7)   一.nova介绍:       Nova 是 OpenStack 最核心的服务,负责维护和管理云环境的计算资源.OpenStack 作为 ...