问:平均每30分钟会有100位客人到银行处理业务,每个顾客的业务处理时间为40~180秒,为了使每个顾客的等待时间尽可能短,应该设置多少窗口?
解题之前首先要确认这个问题的逻辑,逻辑没确定清楚的话程序写不对。
忽略顾客到来的时间,一位顾客到银行后需要进行什么判断呢?
看看是否有窗口,没有空窗口就看哪个窗口的人数最短。
而在本题中排队人数多少和等待时间没有绝对关系。
例如:即使只有两个人在前面,但是每个人需要的业务处理时间都为180秒,而隔壁窗口虽然有四个人但是每个人的业务处理时间都为40秒,所以人数多的窗口反而等待时间更短。
所以无法通过窗口前的人数来决定将该顾客安排到窗口。
那么有两种办法解决:
- 每个窗口都设置为一个二维数组,将所有排队的顾客的处理时间和等待时间记录,同时给每个窗口设置参数,将正在排队顾客的处理时间全部相加,这样就能判断哪个窗口能最快处理结束。
这种方法的缺点是程序每次都要修改所有代表窗口的数组的等待时间和每个数组第一个元素 -1(表示每个窗口当前顾客的业务处理时间),运算量较大 - 设置一个数组用于存放需要等待的顾客,即每个顾客到达时,先判断等待组是否有顾客,等待组有顾客,该顾客进入等待组尾等待,这样程序只需要修改等待组的等待时间即可。用一个一维数组代表所有窗口,程序每次将组内所有元素 -1(表示所有窗口当前顾客的业务处理时间),有空窗口时处理等待组第一位顾客。
解决了第一种方法的缺点,运算量较小
(多嘴一句,这种问题换个皮就是另一个问题,实际上解题核心都差不多)
附代码
#include<stdio.h>
#include<math.h>
#include<time.h>
main()
{
int AllTime=0; //时间标准
int Quantity=8; //设置窗口数目
int Window[8]={0}; //假设窗口数目为Quantity,为0时表示空闲,为1时表示忙
int WindowWorkTime[8]={0}; //每个窗口的数字表示剩余处理时间,为0时表示处理结束(空闲)
int Wait[20]={0}; //等待组,当所有窗口均为忙时,顾客进入排队状态
//本算法秉承先到先处理原则,即每个顾客到达时
//若有空闲窗口而等待组没顾客,窗口处理该顾客
//若有空闲窗口而等待组有顾客,该顾客进入等待组尾等待,窗口处理等待组第一位顾客
//若无空闲窗口,该顾客进入等待组尾等待
int WaitNumber=0; //等待的顾客数量
int WaitTime=0; //总的等待时间
int n=0,x=0,y=0,i=0,j=0,k=0,a=0,b=0,c=0,q=0; //用于打印数据的变量,无意义
int Customer[100][2]={0}; //客户到达时间和处理时间
srand((unsigned)time(NULL)); //随机生成100个顾客的到达时间和所需处理时间
for(a=0; a<100; a++)
{
Customer[a][0]=rand()%1500+1;
Customer[a][1]=rand()%141+40;
}
for(a=0; a<100; a++)
{
for(b=0; b<2; b++)
printf("%d ",Customer[a][b]);
printf("\n");
}
printf("-------------------------------------------------------\n");
for(AllTime=0; AllTime<1860; AllTime++) //以每个循环为单位时间
{
for(n=0; n<100; n++) //遍历顾客组,查找当前时间是否有顾客到达
{
if(AllTime==Customer[n][0]) //如果顾客到达
{
if(Wait[0]!=0) //此时已经有顾客在等待(等待组第一位有数据即至少有一位顾客在等待)
{
Wait[WaitNumber]=Customer[n][1]; //该顾客进入等待组尾
WaitNumber++;
}
else //没有顾客在等待
for(i=0; i<Quantity; i++) //查看是否有空闲窗口
{
if(Window[i]==0) //空闲窗口的为0
{
Window[i]=1; //将该窗口改为1(表示忙)
WindowWorkTime[i]=Customer[n][1]; //将顾客所需处理时间导入对应工作窗口
break;
}
if(i==Quantity-1) //若没有空闲窗口
{
Wait[WaitNumber]=Customer[n][1]; //将顾客的处理时间导入等待组,表示有顾客在等待
WaitNumber++; //按先来后到排序,等待组有顺序,一旦有窗口空闲,先到的先处理
}
}
}
}
for(y=0; y<Quantity; y++) //遍历所有工作窗口
{
if(WindowWorkTime[y]==0) //若有工作窗口结束处理
{
Window[y]=0; //离开的顾客所在窗口变为空闲
if(Wait[0]!=0) //如果有顾客在等待(等待组第一位有数据即至少有一位顾客在等待)
{
WindowWorkTime[y]=Wait[0]; //刷新工作窗口处理时间
for(j=0; j<WaitNumber; j++) //等待组数据前移一位(最先等的顾客开始处理)
{
Wait[j]=Wait[j+1];
}
WaitNumber--; //等待的顾客数减一
}
}
}
for(k=0; k<20; k++) //记录总的等待时间
{
//printf("%d\t",Wait[k]);
if(Wait[k]!=0)
WaitTime++;
}
for(q=0; q<Quantity; q++) //打印所有工作窗口的剩余处理时间
{
printf("%d ",WindowWorkTime[q]);
}
printf("\n");
for(c=0; c<Quantity; c++) //所有忙窗口处理时间-1
if(WindowWorkTime[c]!=0)
WindowWorkTime[c]=WindowWorkTime[c]-1;
}
printf("所有顾客的等待时间为%d秒\n",WaitTime);
printf("所有顾客的平均等待时间为%d秒\n",WaitTime/100);
}