超市出口问题

 

一.实验题目
有个超市要开业了(营业时间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个结账出口时的顾客不满意率
思路:将顾客的进队时间分散到各个时间点上,每个时间点只有一个顾客进队,而且这个顾客进队之前都要判断哪个队是最短的,然后进到最短的那个队中。出队的时候可同时有一个或者多个顾客出队,只要这个顾客的出队时间到了就可以出队。程序里面用 timeflagA timeflagB timeflagC servicetime[30] 作为 时间标记,时间标记是根据 randomtime 往后推的。当i等于时间标记时当前的顾客就可以出队了。19:00之前有顾客进队,19:00之后没有顾客进队,但仍然有顾客在排队,所以必须保证当i循环完后所有的顾客都已经出队。出队过程中判断顾客是否满意并记录不满意的顾客数,循环结束之后就可以知道总的不满意顾客数,就可以求出顾客的不满意率。
2. 如果要求顾客不满意率降到2%,至少应有多少出口?
由实际情况可知当中只有一个队的时候不满意率为最高,队越多不满意率越低,当队达到某个数量时不满意率会降至0,所以要将不满意率降到2%只需将队的数目循环递增即可,当达到要求后终止。
 
 
 
第一问
 
 
  1. #include"stdio.h"  
  2. #include"stdlib.h"  
  3. #include"math.h"  
  4. #include"time.h"  
  5. #define maxsize 300//设定每个队的最大长度为300,实际情况每个队不可能排300个人  
  6. #define mu 2.0 //平均两分钟  
  7. #define sigma 1.0 //方差为1  
  8. int unsat=0;//不满意顾客数  
  9. int total=0;//总顾客数  
  10. int randomtime=0;  
  11. FILE * fp;  
  12.  
  13. typedef struct customer  
  14. {  
  15.        int number;//第几号顾客  
  16.        int EnQueueTime;//进队时间  
  17. }customer;  
  18. typedef struct Queue  
  19. {  
  20.        int rear,front;  
  21.        customer element[maxsize];  
  22. }Queue;  
  23. //-------------------------------------------------------------------------------  
  24. double random(void)  
  25. {  
  26.        int a;  
  27.        double r;  
  28.        a=rand()%32767;  
  29.        r=(a+0.00)/32767.00;  
  30.        return r;  
  31. }  
  32. int Random()  
  33. {  
  34.        int i,m;  
  35.        shang:  
  36.        {  
  37.               double r,sum=0.0;     
  38.               for(i=1;i<=12;i++)  
  39.               sum=sum+random();  
  40.               r=(sum-6.00)*sigma+mu;  
  41.               m=(int)(r*60);//转化成整数秒  
  42.        }  
  43.        if(m<60||m>180)  
  44.               goto shang;//若产生的随机时间小于60秒或者大于180秒则重新产生  
  45.        return  m;  
  46. }                                                                                  //这段产生随机数的代码是网上找的  
  47. //-------------------------------------------------------------------------------  
  48. void converttime(int time)//转换时间  
  49. {//将循环中i对应的时间转换成为几点几分几秒  
  50.        int a,b,c;  
  51.        a=(time/3600+8)%24;//时  
  52.        b=(time%3600)/60;//分  
  53.        c=time%60;//秒  
  54.        if(a<10)//小时  
  55.        {  
  56.               printf("0%d:",a);  
  57.               fprintf(fp,"0%d:\r",a);  
  58.        }  
  59.        else 
  60.        {  
  61.               printf("%d:",a);  
  62.               fprintf(fp,"%d:\r",a);  
  63.        }  
  64.        if(b<10)//分钟  
  65.        {  
  66.               printf("0%d:",b);  
  67.               fprintf(fp,"0%d:\r",b);  
  68.        }  
  69.        else 
  70.        {  
  71.               printf("%d:",b);  
  72.               fprintf(fp,"%d:\r",b);  
  73.        }  
  74.        if(c<10)//秒  
  75.        {  
  76.               printf("0%d ",c);  
  77.               fprintf(fp,"0%d \r",c);  
  78.        }  
  79.        else 
  80.        {  
  81.               printf("%d ",c);  
  82.               fprintf(fp,"%d \r",c);  
  83.        }  
  84. }//-------------------------------------------------------------------------------  
  85. void initQueue(Queue *Q)//初始化队列  
  86. {  
  87.        Q->front=Q->rear=0;  
  88. }//-------------------------------------------------------------------------------  
  89. int length(Queue *Q)//求队列长度  
  90. {  
  91.        return (Q->rear+maxsize-Q->front)%maxsize;  
  92. }//-------------------------------------------------------------------------------  
  93. int EnQueue(Queue *Q,int num,int time)//进队  
  94. {  
  95.        if((Q->rear+1)%maxsize==Q->front)  
  96.               return 0;  
  97.        Q->element[Q->rear].number=num;  
  98.        Q->element[Q->rear].EnQueueTime=time;//存储进队时间  
  99.        Q->rear=(Q->rear+1)%maxsize;  
  100.        return 1;  
  101. }//-------------------------------------------------------------------------------  
  102. int DeQueue1(Queue *Q,int time,int order)//闲时对应的出队函数,order为队列的序号  
  103. {  
  104.        if(length(Q)==0)  
  105.               return 0;  
  106.        converttime(time);//转换时间  
  107.        printf("第%d号顾客出第%d队  这位顾客开始排队的时间是:",Q->element[Q->front].number,order);  
  108.        fprintf(fp,"第%d号顾客出第%d队\r",Q->element[Q->front].number,order);   
  109.        fprintf(fp," 这位顾客开始排队的时间是:\r");   
  110.        converttime(Q->element[Q->front].EnQueueTime);   
  111.        if(time-Q->element[Q->front].EnQueueTime>180)  
  112.        {  
  113.               unsat++;//如果排队的时间超过180秒则不满意数加1  
  114.               fprintf(fp," 不满意!\r\n");  
  115.               printf(" 不满意!\n");  
  116.        }  
  117.        else 
  118.        {            
  119.               fprintf(fp," 满意!\r\n");  
  120.               printf(" 满意!\n");  
  121.        }  
  122.        Q->front=(Q->front+1)%maxsize;  
  123.        return 1;  
  124. }//-------------------------------------------------------------------------------  
  125. int DeQueue2(Queue *Q,int time,int order)////忙时对应的出队函数  
  126. {  
  127.        if(length(Q)==0)  
  128.               return 0;       
  129.        converttime(time);//转换时间  
  130.        printf("第%d号顾客出第%d队  这位顾客开始排队的时间是:",Q->element[Q->front].number,order);  
  131.        fprintf(fp,"第%d号顾客出第%d队\r",Q->element[Q->front].number,order);  
  132.        fprintf(fp," 这位顾客开始排队的时间是:\r");  
  133.        converttime(Q->element[Q->front].EnQueueTime);  
  134.        if(time-Q->element[Q->front].EnQueueTime>300)  
  135.        {  
  136.               unsat++;//如果排队的时间超过300秒则不满意数加1      
  137.               fprintf(fp," 不满意!\r\n");  
  138.               printf(" 不满意!\n");  
  139.        }  
  140.        else 
  141.        {  
  142.               fprintf(fp," 满意!\r\n");  
  143.               printf(" 满意!\n");  
  144.        }  
  145.        Q->front=(Q->front+1)%maxsize;//front后移  
  146.        return 1;  
  147. }//-------------------------------------------------------------------------------  
  148. void main()  
  149. {  
  150.     clock_t start;   
  151.     clock_t end;  
  152.     start =time(NULL);  
  153.        fp = fopen("三个出口时的排队情况.txt","a");//以追加方式写入  
  154.        fprintf(fp,"超市有三个出口时的排队情况\r\n");  
  155.        int i=1;  
  156.        int timeflagA=Random();//时间标记  
  157.        int timeflagB=Random();  
  158.        int timeflagC=Random();  
  159.        Queue A,B,C;  
  160.        initQueue(&A);  
  161.        initQueue(&B);  
  162.        initQueue(&C);  
  163.        int customertime;//=60;  
  164.        while(i<=70000)//8:00-19:00之间的四个小时共39600秒,加5分钟300秒  
  165.        {  
  166.               if(i<=39600)//i=39600对应时间是19:00,之后没有顾客进队  
  167.               {  
  168.                      if(i<=14400||(i>21600&&i<=32400))//闲时  
  169.                             customertime=60;  
  170.                      else //if((i>14400&&i<=21600)||(i>32400&&i<=39600))//忙时  
  171.                             customertime=12;  
  172.                      if(i%customertime==0)//有人来排队,customertime为一个人来排队到另外一个人来排队之间的间隔时间  
  173.                      {             
  174.                             if(length(&A)<=length(&B)&&length(&A)<=length(&C))  
  175.                             {  
  176.                                    total++;  
  177.                                    EnQueue(&A,total,i);//A队最短            
  178.                             }  
  179.                             else if(length(&B)<=length(&A)&&length(&B)<=length(&C))  
  180.                             {  
  181.                                    total++;  
  182.                                    EnQueue(&B,total,i);//B队最短,total表示来的第几个顾客,i为进队时间    
  183.                             }  
  184.                             else 
  185.                             {  
  186.                                    total++;  
  187.                                    EnQueue(&C,total,i);//C队最短  
  188.                             }  
  189.                      }  
  190.               }//if(i<=39600)  
  191.               if(i==timeflagA)  
  192.               {  
  193.                      if(i<=14400||(i>21600&&i<=32400))  
  194.                             DeQueue1(&A,i,1);   //i为出队时间  
  195.                      else 
  196.                             DeQueue2(&A,i,1);  
  197.                      randomtime=Random();//randomtime即为下一名顾客的服务时间  
  198.                      timeflagA=randomtime+timeflagA;        
  199.               }  
  200.               if(i==timeflagB)  
  201.               {  
  202.                      if(i<=14400||(i>21600&&i<=32400))  
  203.                             DeQueue1(&B,i,2);  
  204.                      else 
  205.                             DeQueue2(&B,i,2);  
  206.                      randomtime=Random();  
  207.                      timeflagB=randomtime+timeflagB;                
  208.               }  
  209.               if(i==timeflagC)  
  210.               {  
  211.                      if(i<=14400||(i>21600&&i<=32400))  
  212.                             DeQueue1(&C,i,3);  
  213.                      else 
  214.                             DeQueue2(&C,i,3);  
  215.                      randomtime=Random();  
  216.                      timeflagC=randomtime+timeflagC;                      
  217.               }  
  218.               i++;  
  219.        }//while(i<=79900)  
  220.        printf("不满意的顾客数为:%d,总的顾客数为:%d\n",unsat,total);  
  221.        printf("不满意率为:%4.2f%%\r\n",((double)unsat/(double)total)*100);  
  222.        fprintf(fp,"总顾客数为%d,其中不满意的顾客数为:%d\r\n",total,unsat);  
  223.        fprintf(fp,"不满意率为:%4.2f%%\r\n",((double)unsat/(double)total)*100);     
  224.        fprintf(fp,"循环结束后的时间为:\r");//连续两个%输出一个%  
  225.        converttime(i);  
  226.        fclose(fp);  
  227.        end = time(NULL);  
  228.        printf("\n程序运行所用时间%d秒\n",end-start);  
  229. }  
  230.  
  231.    
  232.  
  233.    
  234.  

 

第二问

 

 
  1. #include"stdio.h"  
  2. #include"stdlib.h"  
  3. #include"math.h"  
  4. #include"time.h"  
  5. #define maxsize 1620//设定每个队的最大长度为1620  
  6. #define mu 2.0 //平均两分钟  
  7. #define sigma 1.0 //方差为1  
  8. int unsat=0;//不满意顾客数  
  9. int total=0;//总顾客数  
  10. int randomtime=0;  
  11. FILE * fp;  
  12. typedef struct customer  
  13. {  
  14.        int number;//第几号顾客  
  15.        int EnQueueTime;//进队时间  
  16. }customer;  
  17. typedef struct Queue  
  18. {  
  19.        int rear,front;  
  20.        customer element[maxsize];  
  21. }Queue;  
  22. //-------------------------------------------------------------------------------  
  23. double random(void)  
  24. {  
  25.        int a;  
  26.        double r;  
  27.        a=rand()%32767;  
  28.        r=(a+0.00)/32767.00;  
  29.        return r;  
  30. }  
  31. int Random()  
  32. {  
  33.        int i,m;  
  34.        shang:  
  35.        {  
  36.               double r,sum=0.0;     
  37.               for(i=1;i<=12;i++)  
  38.               sum=sum+random();  
  39.               r=(sum-6.00)*sigma+mu;  
  40.               m=(int)(r*60);//转化成整数秒  
  41.        }  
  42.        if(m<60||m>180)  
  43.               goto shang;//若产生的随机时间小于60秒或者大于180秒则重新产生  
  44.        return m;  
  45. }                                                                                  //这段产生随机数的代码是网上找的  
  46. //-------------------------------------------------------------------------------  
  47. void converttime(int time)//转换时间  
  48. {//将循环中i对应的时间转换成为几点几分几秒  
  49.        int a,b,c;  
  50.        a=(time/3600+8)%24;//时  
  51.        b=(time%3600)/60;//分  
  52.        c=time%60;//秒  
  53.        if(a<10)//小时  
  54.        {  
  55.               printf("0%d:",a);  
  56.               fprintf(fp,"0%d:\r",a);  
  57.        }  
  58.        else 
  59.        {  
  60.               printf("%d:",a);  
  61.               fprintf(fp,"%d:\r",a);  
  62.        }  
  63.        if(b<10)//分钟  
  64.        {  
  65.               printf("0%d:",b);  
  66.               fprintf(fp,"0%d:\r",b);  
  67.        }  
  68.        else 
  69.        {  
  70.               printf("%d:",b);  
  71.               fprintf(fp,"%d:\r",b);  
  72.        }  
  73.        if(c<10)//秒  
  74.        {  
  75.               printf("0%d ",c);  
  76.               fprintf(fp,"0%d \r",c);  
  77.        }  
  78.        else 
  79.        {  
  80.               printf("%d ",c);  
  81.               fprintf(fp,"%d \r",c);  
  82.        }  
  83. }//-------------------------------------------------------------------------------  
  84. void initQueue(Queue *Q)//初始化队列  
  85. {  
  86.        Q->front=0;  
  87.        Q->rear=0;  
  88. }//-------------------------------------------------------------------------------  
  89. int length(Queue *Q)//求队列长度  
  90. {  
  91.        return (Q->rear+maxsize-Q->front)%maxsize;  
  92. }//-------------------------------------------------------------------------------  
  93. int EnQueue(Queue *Q,int num,int time)//进队  
  94. {  
  95.        if((Q->rear+1)%maxsize==Q->front)  
  96.               return 0;  
  97.        Q->element[Q->rear].number=num;  
  98.        Q->element[Q->rear].EnQueueTime=time;//存储进队时间  
  99.        Q->rear=(Q->rear+1)%maxsize;//rear后移  
  100.        return 1;  
  101. }//-------------------------------------------------------------------------------  
  102. int DeQueue1(Queue *Q,int time,int order)//闲时对应的出队函数,order为队列的序号  
  103. {  
  104.        if(length(Q)==0)  
  105.               return 0;  
  106.        converttime(time);//转换时间  
  107.        printf("第%d号顾客出第%d队  这位顾客开始排队的时间是:",Q->element[Q->front].number,order);  
  108.        fprintf(fp,"第%d号顾客出第%d队\r",Q->element[Q->front].number,order);   
  109.        fprintf(fp," 这位顾客开始排队的时间是:\r");   
  110.        converttime(Q->element[Q->front].EnQueueTime);   
  111.        if(time-Q->element[Q->front].EnQueueTime>180)  
  112.        {  
  113.               unsat++;//如果排队的时间超过180秒则不满意数加1  
  114.               fprintf(fp," 不满意!unsat=%d\r\n",unsat);  
  115.               printf(" 不满意!\n");  
  116.        }  
  117.        else 
  118.        {            
  119.               fprintf(fp," 满意!\r\n");  
  120.               printf(" 满意!\n");  
  121.        }  
  122.        Q->front=(Q->front+1)%maxsize;  
  123.        return 1;  
  124. }//-------------------------------------------------------------------------------  
  125. int DeQueue2(Queue *Q,int time,int order)////忙时对应的出队函数  
  126. {  
  127.        if(length(Q)==0)  
  128.               return 0;       
  129.        converttime(time);//转换时间  
  130.        printf("第%d号顾客出第%d队  这位顾客开始排队的时间是:",Q->element[Q->front].number,order);  
  131.        fprintf(fp,"第%d号顾客出第%d队\r",Q->element[Q->front].number,order);  
  132.        fprintf(fp," 这位顾客开始排队的时间是:\r");  
  133.        converttime(Q->element[Q->front].EnQueueTime);  
  134.        if(time-Q->element[Q->front].EnQueueTime>300)  
  135.        {  
  136.               unsat++;//如果排队的时间超过300秒则不满意数加1      
  137.               fprintf(fp," 不满意!unsat=%d\r\n",unsat);  
  138.               printf(" 不满意!\n");  
  139.        }  
  140.        else 
  141.        {  
  142.               fprintf(fp," 满意!\r\n");  
  143.               printf(" 满意!\n");  
  144.        }  
  145.        Q->front=(Q->front+1)%maxsize;//front后移  
  146.        return 1;  
  147. }//-------------------------------------------------------------------------------  
  148. void main()  
  149. {  
  150.     clock_t start;   
  151.     clock_t end;  
  152.     start =time(NULL);  
  153.    
  154.     fp = fopen("超市出口问题第二问beta1.txt","a");//以追加方式写入  
  155.     int i,j,k=0,m=1,n=0;  
  156.     int customertime;  
  157.     int servicetime[50];//服务时间标记      
  158.     Queue Q[50];  
  159.     while(1)  
  160.     {  
  161.         fprintf(fp,"有%d个出口时的排队情况\r\n",m);  
  162.         unsat=0;  
  163.         total=0;  
  164.         i=1;  
  165.         for(j=0;j<m;j++)  
  166.         {  
  167.             initQueue(&Q[j]);  
  168.             servicetime[j]=Random();  
  169.         }  
  170.         while(i<=800000)//8:00-19:00之间的四个小时共39600秒,加5分钟300秒  
  171.         {  
  172.             if(i<=39600)//i=39600对应时间是19:00,之后没有顾客进队  
  173.             {     
  174.                 if(i<=14400||(i>21600&&i<=32400))//闲时  
  175.                     customertime=60;/////////////////////////////////////////////////////////////////////////////////////  
  176.                 else //if((i>14400&&i<=21600)||(i>32400&&i<=39600))//忙时  
  177.                     customertime=12;/////////////////////////////////////////////////////////////////////////////////////  
  178.                 if(i%customertime==0)//有人来排队,customertime为一个人来排队到另外一个人来排队之间的间隔时间  
  179.                 {             
  180.                     for(j=0;j<m;j++)  
  181.                     {  
  182.                         if(length(&Q[j])<length(&Q[n]))  
  183.                             n=j;  
  184.                     }  
  185.                     total++;  
  186.                     EnQueue(&Q[n],total,i);//A队最短  
  187.                 }  
  188.             }//if(i<=39600)  
  189.             for(j=0;j<m;j++)  
  190.             {  
  191.                 if(i==servicetime[j])  
  192.                 {  
  193.                     if(i<=14400||(i>21600&&i<=32400))  
  194.                         DeQueue1(&Q[j],i,j+1);   //i为出队时间  
  195.                     else 
  196.                         DeQueue2(&Q[j],i,j+1);  
  197.                     randomtime=Random();//randomtime即为下一名顾客的服务时间  
  198.                     servicetime[j]=randomtime+servicetime[j];        
  199.                 }  
  200.             }  
  201.             i++;  
  202.         }//while(i<=79900)  
  203.         printf("不满意的顾客数为:%d,总的顾客数为:%d\n",unsat,total);  
  204.         printf("不满意率为:%4.2f%%\r\n",((double)unsat/(double)total)*100);  
  205.         fprintf(fp,"总顾客数为%d,其中不满意的顾客数为:%d\r\n",total,unsat);  
  206.         fprintf(fp,"不满意率为:%4.2f%%\r\n",((double)unsat/(double)total)*100);   
  207.         fprintf(fp,"循环结束后的时间为:\r");  
  208.         converttime(i);       
  209.         if(((double)unsat/(double)total)<0.02)  
  210.         {  
  211.             fprintf(fp,"\n当有%d个出口时,不满意率低于2%%  O(∩_∩)O~~\r\n",m);  
  212.             break;  
  213.         }  
  214.         else   
  215.         {  
  216.             fprintf(fp,"\n当有%d个出口时,不满意率高于2%%\r\n-----------------------------------------------------------------------------------------------\n",m);  
  217.             m++;              
  218.         }  
  219.     }//while(1)   
  220.     fclose(fp);   
  221.     end = time(NULL);  
  222.     printf("\n程序运行所用时间%d秒\n",end-start);  
  223.  
  224. }  

 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值