zoukankan      html  css  js  c++  java
  • 超市问题

    一.实验题目
    有个超市要开业了(营业时间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文档中。
    有3个结账出口时的顾客不满意率
    思路:将顾客的进队时间分散到各个时间点上,每个时间点只有一个顾客进队,而且这个顾客进队之前都要判断哪个队是最短的,然后进到最短的那个队中。出队的时候可同时有一个或者多个顾客出队,只要这个顾客的出队时间到了就可以出队。程序里面用timeflagA、timeflagB、timeflagC、servicetime[30]作为时间标记,时间标记是根据randomtime往后推的。当i等于时间标记时当前的顾客就可以出队了。19:00之前有顾客进队,19:00之后没有顾客进队,但仍然有顾客在排队,所以必须保证当i循环完后所有的顾客都已经出队。出队过程中判断顾客是否满意并记录不满意的顾客数,循环结束之后就可以知道总的不满意顾客数,就可以求出顾客的不满意率。
    如果要求顾客不满意率降到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 randomX(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+randomX();
                  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;
    }//-------------------------------------------------------------------------------
    int main()
    {
           time_t start,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("
    The program used %-.2f seconds.
    ",difftime(end,start));
    
           return 0;
    }
    
    
    #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 randomX(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+randomX();
                  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;
    }//-------------------------------------------------------------------------------
    int main()
    {
        time_t start,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("
    The program used %-.2f seconds.
    ",difftime(end,start));
        return 0;
    }
    
  • 相关阅读:
    Delphi XE5 android 蓝牙通讯传输
    Delphi XE5 android toast
    Delphi XE5 android openurl(转)
    Delphi XE5 如何设计并使用FireMonkeyStyle(转)
    Delphi XE5 android 捕获几个事件
    Delphi XE5 android listview
    Delphi XE5 android 黑屏的临时解决办法
    Delphi XE5 android popumenu
    Delphi XE5 android 获取网络状态
    Delphi XE5 android 获取电池电量
  • 原文地址:https://www.cnblogs.com/umgsai/p/11673143.html
Copyright © 2011-2022 走看看