PTA银行排队问题之单队列多窗口加VIP服务

该博客讨论了一个银行排队问题的模拟,其中考虑了VIP客户的优先服务。问题描述了一个包含多个窗口和VIP窗口的系统,VIP客户在有空闲窗口时优先处理。博主提供了AC代码来解决这个问题,计算了平均等待时间、最长等待时间和最后完成时间,并统计了每个窗口的服务人数。代码使用链表数据结构处理队列,并实现了VIP客户的插队机制。
摘要由CSDN通过智能技术生成

3-7 银行排队问题之单队列多窗口加VIP服务 (20 分)

假设银行有K个窗口提供服务,窗口前设一条黄线,所有顾客按到达时间在黄线后排成一条长龙。当有窗口空闲时,下一位顾客即去该窗口处理事务。当有多个窗口可选择时,假设顾客总是选择编号最小的窗口。

有些银行会给VIP客户以各种优惠服务,例如专门开辟VIP窗口。为了最大限度地利用资源,VIP窗口的服务机制定义为:当队列中没有VIP客户时,该窗口为普通顾客服务;当该窗口空闲并且队列中有VIP客户在等待时,排在最前面的VIP客户享受该窗口的服务。同时,当轮到某VIP客户出列时,若VIP窗口非空,该客户可以选择空闲的普通窗口;否则一定选择VIP窗口。

本题要求输出前来等待服务的N位顾客的平均等待时间、最长等待时间、最后完成时间,并且统计每个窗口服务了多少名顾客。

输入格式:
输入第1行给出正整数N(≤1000),为顾客总人数;随后N行,每行给出一位顾客的到达时间T、事务处理时间P和是否VIP的标志(1是VIP,0则不是),并且假设输入数据已经按到达时间先后排好了顺序;最后一行给出正整数K(≤10)—— 为开设的营业窗口数,以及VIP窗口的编号(从0到K−1)。这里假设每位顾客事务被处理的最长时间为60分钟。

输出格式:
在第一行中输出平均等待时间(输出到小数点后1位)、最长等待时间、最后完成时间,之间用1个空格分隔,行末不能有多余空格。

在第二行中按编号递增顺序输出每个窗口服务了多少名顾客,数字之间用1个空格分隔,行末不能有多余空格。

输入样例:

10
0 20 0
0 20 0
1 68 1
1 12 1
2 15 0
2 10 0
3 15 1
10 12 1
30 15 0
62 5 1
3 1
结尾无空行

输出样例:

15.1 35 67
4 5 1
结尾无空行

思路:

新增的VIP功能其实就是在队列里有VIP且有VIP窗口的情况下,将VIP放到VIP窗口
所以只需在FUNCTION的开头添加一个判断即可,本题存在插队问题,
所以用链表存储会简单一点

AC代码如下:

#include<stdio.h>
#include <stdlib.h>
struct Node{
	int T;
	int P;
	int V;
	struct Node* next;
};
typedef struct Node* Q;
struct Queue{
	Q front;
	Q last;
};
typedef struct Queue* List;
List create();
void insert(List l,int a,int b,int c);
int Look(List l);
void get(List l,int* t,int* p);//正常出队
void getVIP(List l,int* t,int* p);//VIP插队
int isEmpty(List l);
int function(List l);

int time=0;
int N,maxWait=-1;
int W[15]={0},W_sum[15]={0},W_cnt,W_vip;
double sum = 0;

int main(){
	int i;
	List l = create();
	scanf("%d",&N);
	for(i=0;i<N;i++){
		int a,b,c;
		scanf("%d %d %d",&a,&b,&c);
		if(b>60)
		b=60;
		insert(l,a,b,c);
	}
	
	
	scanf("%d %d",&W_cnt,&W_vip);
	while(1){
		int flag = function(l);
		if(flag==1)
		break;
		time++;
	}
	printf("%.1f %d %d\n",sum/N,maxWait,time);
	for(i=0;i<W_cnt;i++){
		printf("%d",W_sum[i]);
		if(i<W_cnt-1)
		printf(" ");
	}
	
	return 0;
}


int function(List l){
	int i;
	int flag = -1;
	/*有VIP窗口和VIP客人时*/
	for(i=0;i<W_cnt;i++){
		if(W[i]==0 && i == W_vip)
		flag = i;
	}
	//printf("*%d*",flag);
	if(flag!=-1 && Look(l)==2){
		int t=0;
        int p=0;
        getVIP(l,&t,&p);
      // printf("%d号窗口接待了 %d %d %d\n",flag,t,p,1);
		if(time-t >maxWait)
		maxWait = time-t;
		sum = sum +time-t;
		W[flag] = p;
		W_sum[flag]++;
	}
	/*有VIP窗口和VIP客人时 End*/
	
	for(i=0;i<W_cnt;i++){
		if(W[i]==0){
   			if(Look(l)==1||Look(l)==2){
               	int t=0;
               	int p=0;
               	get(l,&t,&p);
               	//printf("%d号窗口接待了 %d %d\n",i,t,p);
				if(time-t >maxWait)
				maxWait = time-t;
				sum = sum +time-t;
				W[i] = p;
				W_sum[i]++;
			}
		}

	}
	//为下一次计时做准备
	int flag1=0;
	for(i=0;i<W_cnt;i++){
		if(W[i]>0){
			flag1=1;
			W[i]--;
		}
	}
	if(flag1==0 && Look(l)==-1)
	return 1;
	return 0;
}

List create(){
	List l = (struct Queue*)malloc(sizeof(struct Queue));
	l->front = (struct Node*)malloc(sizeof(struct Node));
	l->front->next = NULL;
	l->front->P=-1;
	l->front->T=-1;
	l->front->V=-1;
	l->last = l->front;
	return l;
}
void insert(List l,int a,int b,int c){
	Q q = (struct Node*)malloc(sizeof(struct Node));
	q->T = a;
	q->P = b;
	q->V = c;
	q->next = NULL;
	l->last->next = q;
	l->last = l->last->next;
}
int Look(List l){
	Q q = l->front->next;
	//队列为空,返回-1
	if(!q) return -1;
	int re = 0;
	//有排队的人 1
	if(q->T<=time)
	re=1;
	//排队的有VIP 2
	while(q){
		if(q->T<=time && q->V == 1)
		re=2;
		q=q->next;
	}
	return re;
}
//删除并返回T,P
void get(List l,int* t,int* p){
	Q q = l->front->next;
	(*p) = q->P;
	(*t) = q->T;
	l->front->next = q->next;
	free(q);
}

//删除并返回T,P
void getVIP(List l,int* t,int* p){
	Q q = l->front;
	while(q->next->V != 1){
		q=q->next;
	}
	(*p) = q->next->P;
	(*t) = q->next->T;
	Q temp = q->next;
	q->next = temp->next;
	free(temp);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苏横3215

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值