• 《C++primerplus》第12章练习题


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

    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
    ";
    
        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
    ";    //平均每个人的等待时间
            }
            else
                cout<<"No customers!
    ";
            cout<<"Done!
    ";
    
            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
    ";
    
        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
    ";    //平均每个人的等待时间
            }
            else
                cout<<"No customers!
    ";
            cout<<"Done!
    ";
    
            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分钟。但是,我翻来覆去地看代码,也不知道为什么平均等待时间会算出负数来,总觉得哪里有问题。

  • 相关阅读:
    SPA项目开发之动态树以及数据表格和分页
    SPA项目开发之首页导航左侧菜单栏
    SPA项目开发之登录
    使用vue-cli搭建spa项目
    Splay 平衡树
    主席树(可持久化线段树 )
    P3195 [HNOI2008]玩具装箱TOY
    P2962 [USACO09NOV]灯Lights
    【hdu4405】AeroplaneChess
    HDU3853:LOOPS
  • 原文地址:https://www.cnblogs.com/banmei-brandy/p/11460755.html
Copyright © 2020-2023  润新知