习题8.2 银行排队问题之单队列多窗口加VIP服务 (30分)--C语言
解题思路:
1、普通客户到来:从编号最小的窗口开始查看是否有空闲窗口
1)如果有空闲窗口,若此时空闲窗口刚好是VIP窗口,则看一下队列里面是否有已经到来的VIP客户,如有,则让该VIP插队
2)如果没有空闲窗口,则寻找最先完成的窗口,若最先完成的窗口也是VIP,同理也要看一下队列里是否有VIP已经到来,如有,则让VIP插队
2、VIP客户到来:首先查看VIP窗口是否空闲,如空闲,则直接办理,若不空闲,则寻找最快完成窗口(这里要注意的是:VIP窗口的优先级排在普通窗口之前)
#include <stdio.h> #include <string.h> typedef struct { int t,p,flag; } Queue; Queue Q[1010]; void ChkVip(int start,int end,int sum) { int i,pos; for(i=start; i<end; i++) { if(Q[i].flag==1&&Q[i].t<sum) {//查看是否有VIP客户已经在等待 pos=i; break; } } if(i<end) {//VIP客户插队 Queue tmp=Q[pos]; for(i=pos-1; i>=start; i--) { Q[i+1]=Q[i]; } Q[start]=tmp; } } int main() { int n,i,min; scanf("%d",&n); int front=0,rear=0; for(i=0; i<n; i++) { scanf("%d %d %d",&Q[rear].t,&Q[rear].p,&Q[rear].flag); if(Q[rear].p>60)Q[rear].p=60; rear++; } int k,c; scanf("%d %d",&k,&c); int sum[k],winnum[k]; memset(sum,0,sizeof(sum)); memset(winnum,0,sizeof(winnum)); int SWT=0,WT=0,LWT=0; while(front<rear) { if(Q[front].flag==0) {//队头是普通客户 min=0; for(i=0; i<k; i++) {//查找空闲窗口 if(Q[front].t>=sum[i]) {//此时无需等待 if(i==c)//当前空闲窗口是VIP窗口,则查找此时是否有Vip客户已经到时来,若vip已经到来,则将vip插队上来 ChkVip(front,n,sum[i]); sum[i]=Q[front].t+Q[front].p; front++; winnum[i]++; break; } if(sum[i]<sum[min]) min=i; } if(i==k) {//已经到来在等待 if(min==c)//当前空闲窗口是VIP窗口,则查找此时是否有Vip客户已经到时来,若vip已经到来,则将vip插队上来 ChkVip(front,n,sum[min]); WT=sum[min]-Q[front].t; if(WT>LWT)LWT=WT; SWT+=WT; sum[min]+=Q[front].p; front++; winnum[min]++; } } else {//队头是VIP客户 if(Q[front].t>=sum[c]) {//查找此时是否有VIP窗口空闲 sum[c]=Q[front].t+Q[front].p; winnum[c]++; front++; } else { min=c; for(i=0; i<k; i++) {//查找最快完成窗口 if(sum[i]<sum[min]) min=i; } if(Q[front].t>=sum[min])//无需等待 sum[min]=Q[front].t+Q[front].p; else {//需等待 WT=sum[min]-Q[front].t; if(WT>LWT)LWT=WT; SWT+=WT; sum[min]+=Q[front].p; } front++; winnum[min]++; } } } int LFT=0; for(i=0; i<k; i++) { if(sum[i]>sum[LFT]) LFT=i; } printf("%.1lf %d %d\n",(double)SWT/n,LWT,sum[LFT]); for(i=0; i<k; i++) { if(i>0) printf(" "); printf("%d",winnum[i]); } return 0; }
勤能补拙,熟能生巧