• 超市出口问题


    一.实验题目
    有个超市要开业了(营业时间8-19点),据经验统计,每个客人来结账的时间服从随机分布,每个顾客需要服务的时间服从正态分布(均值为2分钟,方差为1分钟),超市平时的顾客较少(8-12点、14-17点),顾客来结账的平均人数为60人/小时,而高峰期(12-14,17-19点)平均人数为300人/小时,平常顾客等待时间超过3分钟则不满意,而高峰期等待5分钟则不满意,顾客总是排在队列长度最短的队列后面。
     
    功能要求:
    1)假设现在超市有3个结账出口,试模拟一天超市出口排队情况,并统计顾客不满意率。
    2)如果要求顾客不满意率降到2%,至少应有多少出口?
     
    二.问题分析
    1.此程序的核心数据结构为队列,顾客的排队过程即为进队与出队过程。
    2.一天中的时间分为两个时间段----闲时和忙时。闲时顾客平均每分钟进队1个,忙时顾客平均每分钟进队5个。由于每个顾客来结账的时间服从随机分布,这里就将各位顾客进队的时间定在各个时间点上,如忙时进队时间分别为:08:01:00、08:02:00、08:03:00、08:04:00……,忙时进队时间分别为:12:00:00、12:00:12、12:00:24、12:00:36……
    3.每个顾客需要服务的时间服从正态分布,平均值2分钟(即120秒),方差1分钟(即60秒)。如果写纯数学函数求随机服务时间,经过测试发现可能产生负数。这里结合实际将每个顾客需要的服务时间限制在60-120秒内。
    4.根据实际情况及题目要求,顾客总是排在最短的队后面,故在每次顾客进队之前都要将最短的那个队列选择出来。
    5.营业时间是从8:00到19:00,程序里面以秒为单位做循环。8:00时对应时间i=0,12:00对应i=14400,14:00对应i=21600,17:00对应i=32400,19:00对应i=39600.在需要显示几点几分几秒的时候再将i转换成时间格式。
     
     
    三.数据结构设计
                                      1.逻辑结构:循环队列
                                      2. 存储结构:数据文件---记事本文件
                                      3. 基本操作列表
                                         *进队与出队操作
                                         *数据文件的数据读写
     
    . 抽象数据类型
    typedef struct customer
    {
           int number;//第几号顾客
           int EnQueueTime;//进队时间
    }customer;
    typedef struct Queue
    {
           int rear,front;
           customer element[maxsize];
    }Queue; 
    五.算法设计
    此程序所需要的数据可直接由系统模拟产生,不需要输入数据,结果输出的数据量较大,故将结果保存在txt文档中。
    1.3个结账出口时的顾客不满意率
    思路:将顾客的进队时间分散到各个时间点上,每个时间点只有一个顾客进队,而且这个顾客进队之前都要判断哪个队是最短的,然后进到最短的那个队中。出队的时候可同时有一个或者多个顾客出队,只要这个顾客的出队时间到了就可以出队。程序里面用timeflagAtimeflagBtimeflagCservicetime[30]作为时间标记,时间标记是根据randomtime往后推的。当i等于时间标记时当前的顾客就可以出队了。19:00之前有顾客进队,19:00之后没有顾客进队,但仍然有顾客在排队,所以必须保证当i循环完后所有的顾客都已经出队。出队过程中判断顾客是否满意并记录不满意的顾客数,循环结束之后就可以知道总的不满意顾客数,就可以求出顾客的不满意率。
    2.如果要求顾客不满意率降到2%,至少应有多少出口?
    由实际情况可知当中只有一个队的时候不满意率为最高,队越多不满意率越低,当队达到某个数量时不满意率会降至0,所以要将不满意率降到2%只需将队的数目循环递增即可,当达到要求后终止。
     
     
     
    第一问
    #include"stdio.h"  
    #include"stdlib.h"  
    #include"math.h"  
    #include"time.h"  
    #define maxsize 300//设定每个队的最大长度为300,实际情况每个队不可能排300个人  
    #define mu 2.0 //平均两分钟  
    #define sigma 1.0 //方差为1  
    int unsat=0;//不满意顾客数  
    int total=0;//总顾客数  
    int randomtime=0;  
    FILE * fp;  
     
    typedef struct customer  
    {  
           int number;//第几号顾客  
           int EnQueueTime;//进队时间  
    }customer;  
    typedef struct Queue  
    {  
           int rear,front;  
           customer element[maxsize];  
    }Queue;  
    //-------------------------------------------------------------------------------  
    double random(void)  
    {  
           int a;  
           double r;  
           a=rand()%32767;  
           r=(a+0.00)/32767.00;  
           return r;  
    }  
    int Random()  
    {  
           int i,m;  
           shang:  
           {  
                  double r,sum=0.0;     
                  for(i=1;i<=12;i++)  
                  sum=sum+random();  
                  r=(sum-6.00)*sigma+mu;  
                  m=(int)(r*60);//转化成整数秒  
           }  
           if(m<60||m>180)  
                  goto shang;//若产生的随机时间小于60秒或者大于180秒则重新产生  
           return  m;  
    }                                                                                  //这段产生随机数的代码是网上找的  
    //-------------------------------------------------------------------------------  
    void converttime(int time)//转换时间  
    {//将循环中i对应的时间转换成为几点几分几秒  
           int a,b,c;  
           a=(time/3600+8)%24;//
           b=(time%3600)/60;//
           c=time%60;//
           if(a<10)//小时  
           {  
                  printf("0%d:",a);  
                  fprintf(fp,"0%d:
    ",a);  
           }  
           else 
           {  
                  printf("%d:",a);  
                  fprintf(fp,"%d:
    ",a);  
           }  
           if(b<10)//分钟  
           {  
                  printf("0%d:",b);  
                  fprintf(fp,"0%d:
    ",b);  
           }  
           else 
           {  
                  printf("%d:",b);  
                  fprintf(fp,"%d:
    ",b);  
           }  
           if(c<10)//
           {  
                  printf("0%d ",c);  
                  fprintf(fp,"0%d 
    ",c);  
           }  
           else 
           {  
                  printf("%d ",c);  
                  fprintf(fp,"%d 
    ",c);  
           }  
    }//-------------------------------------------------------------------------------  
    void initQueue(Queue *Q)//初始化队列  
    {  
           Q->front=Q->rear=0;  
    }//-------------------------------------------------------------------------------  
    int length(Queue *Q)//求队列长度  
    {  
           return (Q->rear+maxsize-Q->front)%maxsize;  
    }//-------------------------------------------------------------------------------  
    int EnQueue(Queue *Q,int num,int time)//进队  
    {  
           if((Q->rear+1)%maxsize==Q->front)  
                  return 0;  
           Q->element[Q->rear].number=num;  
           Q->element[Q->rear].EnQueueTime=time;//存储进队时间  
           Q->rear=(Q->rear+1)%maxsize;  
           return 1;  
    }//-------------------------------------------------------------------------------  
    int DeQueue1(Queue *Q,int time,int order)//闲时对应的出队函数,order为队列的序号  
    {  
           if(length(Q)==0)  
                  return 0;  
           converttime(time);//转换时间  
           printf("第%d号顾客出第%d队  这位顾客开始排队的时间是:",Q->element[Q->front].number,order);  
           fprintf(fp,"第%d号顾客出第%d队
    ",Q->element[Q->front].number,order);   
           fprintf(fp," 这位顾客开始排队的时间是:
    ");   
           converttime(Q->element[Q->front].EnQueueTime);   
           if(time-Q->element[Q->front].EnQueueTime>180)  
           {  
                  unsat++;//如果排队的时间超过180秒则不满意数加1  
                  fprintf(fp," 不满意!
    ");  
                  printf(" 不满意!
    ");  
           }  
           else 
           {            
                  fprintf(fp," 满意!
    ");  
                  printf(" 满意!
    ");  
           }  
           Q->front=(Q->front+1)%maxsize;  
           return 1;  
    }//-------------------------------------------------------------------------------  
    int DeQueue2(Queue *Q,int time,int order)////忙时对应的出队函数  
    {  
           if(length(Q)==0)  
                  return 0;       
           converttime(time);//转换时间  
           printf("第%d号顾客出第%d队  这位顾客开始排队的时间是:",Q->element[Q->front].number,order);  
           fprintf(fp,"第%d号顾客出第%d队
    ",Q->element[Q->front].number,order);  
           fprintf(fp," 这位顾客开始排队的时间是:
    ");  
           converttime(Q->element[Q->front].EnQueueTime);  
           if(time-Q->element[Q->front].EnQueueTime>300)  
           {  
                  unsat++;//如果排队的时间超过300秒则不满意数加1      
                  fprintf(fp," 不满意!
    ");  
                  printf(" 不满意!
    ");  
           }  
           else 
           {  
                  fprintf(fp," 满意!
    ");  
                  printf(" 满意!
    ");  
           }  
           Q->front=(Q->front+1)%maxsize;//front后移  
           return 1;  
    }//-------------------------------------------------------------------------------  
    void main()  
    {  
        clock_t start;   
        clock_t end;  
        start =time(NULL);  
           fp = fopen("三个出口时的排队情况.txt","a");//以追加方式写入  
           fprintf(fp,"超市有三个出口时的排队情况
    ");  
           int i=1;  
           int timeflagA=Random();//时间标记  
           int timeflagB=Random();  
           int timeflagC=Random();  
           Queue A,B,C;  
           initQueue(&A);  
           initQueue(&B);  
           initQueue(&C);  
           int customertime;//=60;  
           while(i<=70000)//8:00-19:00之间的四个小时共39600秒,加5分钟300秒  
           {  
                  if(i<=39600)//i=39600对应时间是19:00,之后没有顾客进队  
                  {  
                         if(i<=14400||(i>21600&&i<=32400))//闲时  
                                customertime=60;  
                         else //if((i>14400&&i<=21600)||(i>32400&&i<=39600))//忙时  
                                customertime=12;  
                         if(i%customertime==0)//有人来排队,customertime为一个人来排队到另外一个人来排队之间的间隔时间  
                         {             
                                if(length(&A)<=length(&B)&&length(&A)<=length(&C))  
                                {  
                                       total++;  
                                       EnQueue(&A,total,i);//A队最短            
                                }  
                                else if(length(&B)<=length(&A)&&length(&B)<=length(&C))  
                                {  
                                       total++;  
                                       EnQueue(&B,total,i);//B队最短,total表示来的第几个顾客,i为进队时间    
                                }  
                                else 
                                {  
                                       total++;  
                                       EnQueue(&C,total,i);//C队最短  
                                }  
                         }  
                  }//if(i<=39600)  
                  if(i==timeflagA)  
                  {  
                         if(i<=14400||(i>21600&&i<=32400))  
                                DeQueue1(&A,i,1);   //i为出队时间  
                         else 
                                DeQueue2(&A,i,1);  
                         randomtime=Random();//randomtime即为下一名顾客的服务时间  
                         timeflagA=randomtime+timeflagA;        
                  }  
                  if(i==timeflagB)  
                  {  
                         if(i<=14400||(i>21600&&i<=32400))  
                                DeQueue1(&B,i,2);  
                         else 
                                DeQueue2(&B,i,2);  
                         randomtime=Random();  
                         timeflagB=randomtime+timeflagB;                
                  }  
                  if(i==timeflagC)  
                  {  
                         if(i<=14400||(i>21600&&i<=32400))  
                                DeQueue1(&C,i,3);  
                         else 
                                DeQueue2(&C,i,3);  
                         randomtime=Random();  
                         timeflagC=randomtime+timeflagC;                      
                  }  
                  i++;  
           }//while(i<=79900)  
           printf("不满意的顾客数为:%d,总的顾客数为:%d
    ",unsat,total);  
           printf("不满意率为:%4.2f%%
    ",((double)unsat/(double)total)*100);  
           fprintf(fp,"总顾客数为%d,其中不满意的顾客数为:%d
    ",total,unsat);  
           fprintf(fp,"不满意率为:%4.2f%%
    ",((double)unsat/(double)total)*100);     
           fprintf(fp,"循环结束后的时间为:
    ");//连续两个%输出一个%  
           converttime(i);  
           fclose(fp);  
           end = time(NULL);  
           printf("
    程序运行所用时间%d秒
    ",end-start);  
    }  

     

    第二问

    #include"stdio.h"  
    #include"stdlib.h"  
    #include"math.h"  
    #include"time.h"  
    #define maxsize 1620//设定每个队的最大长度为1620  
    #define mu 2.0 //平均两分钟  
    #define sigma 1.0 //方差为1  
    int unsat=0;//不满意顾客数  
    int total=0;//总顾客数  
    int randomtime=0;  
    FILE * fp;  
    typedef struct customer  
    {  
           int number;//第几号顾客  
           int EnQueueTime;//进队时间  
    }customer;  
    typedef struct Queue  
    {  
           int rear,front;  
           customer element[maxsize];  
    }Queue;  
    //-------------------------------------------------------------------------------  
    double random(void)  
    {  
           int a;  
           double r;  
           a=rand()%32767;  
           r=(a+0.00)/32767.00;  
           return r;  
    }  
    int Random()  
    {  
           int i,m;  
           shang:  
           {  
                  double r,sum=0.0;     
                  for(i=1;i<=12;i++)  
                  sum=sum+random();  
                  r=(sum-6.00)*sigma+mu;  
                  m=(int)(r*60);//转化成整数秒  
           }  
           if(m<60||m>180)  
                  goto shang;//若产生的随机时间小于60秒或者大于180秒则重新产生  
           return m;  
    }                                                                                  //这段产生随机数的代码是网上找的  
    //-------------------------------------------------------------------------------  
    void converttime(int time)//转换时间  
    {//将循环中i对应的时间转换成为几点几分几秒  
           int a,b,c;  
           a=(time/3600+8)%24;//
           b=(time%3600)/60;//
           c=time%60;//
           if(a<10)//小时  
           {  
                  printf("0%d:",a);  
                  fprintf(fp,"0%d:
    ",a);  
           }  
           else 
           {  
                  printf("%d:",a);  
                  fprintf(fp,"%d:
    ",a);  
           }  
           if(b<10)//分钟  
           {  
                  printf("0%d:",b);  
                  fprintf(fp,"0%d:
    ",b);  
           }  
           else 
           {  
                  printf("%d:",b);  
                  fprintf(fp,"%d:
    ",b);  
           }  
           if(c<10)//
           {  
                  printf("0%d ",c);  
                  fprintf(fp,"0%d 
    ",c);  
           }  
           else 
           {  
                  printf("%d ",c);  
                  fprintf(fp,"%d 
    ",c);  
           }  
    }//-------------------------------------------------------------------------------  
    void initQueue(Queue *Q)//初始化队列  
    {  
           Q->front=0;  
           Q->rear=0;  
    }//-------------------------------------------------------------------------------  
    int length(Queue *Q)//求队列长度  
    {  
           return (Q->rear+maxsize-Q->front)%maxsize;  
    }//-------------------------------------------------------------------------------  
    int EnQueue(Queue *Q,int num,int time)//进队  
    {  
           if((Q->rear+1)%maxsize==Q->front)  
                  return 0;  
           Q->element[Q->rear].number=num;  
           Q->element[Q->rear].EnQueueTime=time;//存储进队时间  
           Q->rear=(Q->rear+1)%maxsize;//rear后移  
           return 1;  
    }//-------------------------------------------------------------------------------  
    int DeQueue1(Queue *Q,int time,int order)//闲时对应的出队函数,order为队列的序号  
    {  
           if(length(Q)==0)  
                  return 0;  
           converttime(time);//转换时间  
           printf("第%d号顾客出第%d队  这位顾客开始排队的时间是:",Q->element[Q->front].number,order);  
           fprintf(fp,"第%d号顾客出第%d队
    ",Q->element[Q->front].number,order);   
           fprintf(fp," 这位顾客开始排队的时间是:
    ");   
           converttime(Q->element[Q->front].EnQueueTime);   
           if(time-Q->element[Q->front].EnQueueTime>180)  
           {  
                  unsat++;//如果排队的时间超过180秒则不满意数加1  
                  fprintf(fp," 不满意!unsat=%d
    ",unsat);  
                  printf(" 不满意!
    ");  
           }  
           else 
           {            
                  fprintf(fp," 满意!
    ");  
                  printf(" 满意!
    ");  
           }  
           Q->front=(Q->front+1)%maxsize;  
           return 1;  
    }//-------------------------------------------------------------------------------  
    int DeQueue2(Queue *Q,int time,int order)////忙时对应的出队函数  
    {  
           if(length(Q)==0)  
                  return 0;       
           converttime(time);//转换时间  
           printf("第%d号顾客出第%d队  这位顾客开始排队的时间是:",Q->element[Q->front].number,order);  
           fprintf(fp,"第%d号顾客出第%d队
    ",Q->element[Q->front].number,order);  
           fprintf(fp," 这位顾客开始排队的时间是:
    ");  
           converttime(Q->element[Q->front].EnQueueTime);  
           if(time-Q->element[Q->front].EnQueueTime>300)  
           {  
                  unsat++;//如果排队的时间超过300秒则不满意数加1      
                  fprintf(fp," 不满意!unsat=%d
    ",unsat);  
                  printf(" 不满意!
    ");  
           }  
           else 
           {  
                  fprintf(fp," 满意!
    ");  
                  printf(" 满意!
    ");  
           }  
           Q->front=(Q->front+1)%maxsize;//front后移  
           return 1;  
    }//-------------------------------------------------------------------------------  
    void main()  
    {  
        clock_t start;   
        clock_t end;  
        start =time(NULL);  
       
        fp = fopen("超市出口问题第二问beta1.txt","a");//以追加方式写入  
        int i,j,k=0,m=1,n=0;  
        int customertime;  
        int servicetime[50];//服务时间标记      
        Queue Q[50];  
        while(1)  
        {  
            fprintf(fp,"有%d个出口时的排队情况
    ",m);  
            unsat=0;  
            total=0;  
            i=1;  
            for(j=0;j<m;j++)  
            {  
                initQueue(&Q[j]);  
                servicetime[j]=Random();  
            }  
            while(i<=800000)//8:00-19:00之间的四个小时共39600秒,加5分钟300秒  
            {  
                if(i<=39600)//i=39600对应时间是19:00,之后没有顾客进队  
                {     
                    if(i<=14400||(i>21600&&i<=32400))//闲时  
                        customertime=60;/////////////////////////////////////////////////////////////////////////////////////  
                    else //if((i>14400&&i<=21600)||(i>32400&&i<=39600))//忙时  
                        customertime=12;/////////////////////////////////////////////////////////////////////////////////////  
                    if(i%customertime==0)//有人来排队,customertime为一个人来排队到另外一个人来排队之间的间隔时间  
                    {             
                        for(j=0;j<m;j++)  
                        {  
                            if(length(&Q[j])<length(&Q[n]))  
                                n=j;  
                        }  
                        total++;  
                        EnQueue(&Q[n],total,i);//A队最短  
                    }  
                }//if(i<=39600)  
                for(j=0;j<m;j++)  
                {  
                    if(i==servicetime[j])  
                    {  
                        if(i<=14400||(i>21600&&i<=32400))  
                            DeQueue1(&Q[j],i,j+1);   //i为出队时间  
                        else 
                            DeQueue2(&Q[j],i,j+1);  
                        randomtime=Random();//randomtime即为下一名顾客的服务时间  
                        servicetime[j]=randomtime+servicetime[j];        
                    }  
                }  
                i++;  
            }//while(i<=79900)  
            printf("不满意的顾客数为:%d,总的顾客数为:%d
    ",unsat,total);  
            printf("不满意率为:%4.2f%%
    ",((double)unsat/(double)total)*100);  
            fprintf(fp,"总顾客数为%d,其中不满意的顾客数为:%d
    ",total,unsat);  
            fprintf(fp,"不满意率为:%4.2f%%
    ",((double)unsat/(double)total)*100);   
            fprintf(fp,"循环结束后的时间为:
    ");  
            converttime(i);       
            if(((double)unsat/(double)total)<0.02)  
            {  
                fprintf(fp,"
    当有%d个出口时,不满意率低于2%%  O(∩_∩)O~~
    ",m);  
                break;  
            }  
            else   
            {  
                fprintf(fp,"
    当有%d个出口时,不满意率高于2%%
    -----------------------------------------------------------------------------------------------
    ",m);  
                m++;              
            }  
        }//while(1)   
        fclose(fp);   
        end = time(NULL);  
        printf("
    程序运行所用时间%d秒
    ",end-start);  
     
    }  

    本文出自 “阿凡达” 博客,请务必保留此出处http://shamrock.blog.51cto.com/2079212/705207

  • 相关阅读:
    C#中枚举的使用
    04 Spring的依赖注入
    03 Spring对Bean的管理
    02 Spring IOC
    01-Spring概述
    java8-方法引用
    java8-Stream
    java8-lambda
    centos中执行apt-get命令提示apt-get command not found
    Eclipse里git提交冲突rejected – non-fast-forward
  • 原文地址:https://www.cnblogs.com/umgsai/p/3908228.html
Copyright © 2020-2023  润新知