PAT 1014 C++版

1.题意

这是一道模拟题,主要考队列的使用和英语题目的阅读理解
题意如下:
给出一个银行的排队规则:
01.有N个窗口
02.每个窗口的黄线前有M个位置可供排队服务。超过M个位置之后的人,就需要在外面排队,直到窗口中黄线内的人数减少,然后进入到黄线内。【如果同一时刻有多个黄线内的人数少于M,则对在外面排队的人会就近选择一个窗口号小的进行服务。】
03.前面一个人服务完成之后,则开始对后面的一个人进行服务。
现在给出一个窗口数N,窗口前的容纳人数M,以及待服务的人数K,最后给出一个查询数Q。

2.分析

如何实现这道题呢?其实思想很简单,如下:
01.首先用N个队列模拟N个银行窗口。
02.每个队列的容量都是M,表示【黄线内的最大的可容纳人数】
03.对队首元素进行服务,队首完成之后,比较每个队列的完成时间,选择一个最小的完成时间的队列,然后删除其队首,接着在尾部插入下一个用户。
04.重复步骤1,2,3
05.当所有的用户都已经被安排之后,进行一个循环,计算出每个队列中用户的完成时间。

3.代码

#include<cstdio>
#include<queue>
#include<iostream>
#define maxn 1005
#define winMaxn 25
 
using namespace std;

int N,M,K,Q;

//有N个窗口 => 队列有N个 
queue<int> que[winMaxn];

//将分钟格式化输出为 小时:分钟 
void printRes(int totalMin){
	int min = totalMin % 60;
	int hour = totalMin / 60;		
	printf("%02d:%02d\n",hour+8,min);
} 

//初始化队列 
void initQue() {
	int i,j;
	int start = 1;	
	for(j = 1;j<= M;j++){ //黄线内的人数 
		start = (j-1) * N + 1;
		for(i = 1;i<= N;i++ ){		
			que[i].push(start);
			start++;
		}
	}
} 

int main(){	
	cin >> N >> M >> K >> Q;
	int i,j;
	int time[maxn];//表示每个人的需求时间	
	int comp[maxn];//表示对K个人的处理结果 
	int query[maxn];//表示查询的序列 
	int curWindow[N+1] = {0};//表示当前窗口的时间 
	
	//输入每个人的处理时间 
	for(i=1;i<=K;i++){
		cin >> time[i];
	}
	
	for(i = 1;i<=Q;i++) { //输入需要查询的人 
		cin >> query[i]; 
	}
	//首先对队列进行初始化处理
	initQue(); 
	
	//对剩下未入队的人进行轮流处理 
	//下标从1 开始 【不是从1开始,因为已经初始化过了】 ,故开始的下标是 N*M+1	
	for(i = N*M+1 ; i <= K;i++){
		//cout <<"当前正在判断的人是:"<<i<<"\n";		
		int minWindow = -1;//最小时间所对应的窗口
		int minTime = 0x3fffffff;//所有窗口中,最小的时间	
						
		for( j = 1; j <= N;j++){ //从1号窗口开始 
		//	cout <<"队首的人是:"<< que[j].front()<<"\n"; 
			int tempTime = ( curWindow[j] + time[que[j].front()] );
			if(minTime > tempTime ){//如果当前窗口的时间小于minTime,则选择更新minTime,并且更新minWindow 
				minWindow = j;
				minTime = tempTime ;
			}
		//	cout <<"minTime = "<<minTime<<"\n";			
		}	
		//cout <<"这次出队的是:"<< que[minWindow].front() <<"\n";		
		curWindow[minWindow] += time[que[minWindow].front()];
		comp[que[minWindow].front()] = curWindow[minWindow];//写入完成的时间 		
		que[minWindow].pop();//将minWindow号窗口的第一个人出队		
		que[minWindow].push(i);//入i 			
	}
	
	//对黄线内的M 个人开始服务 
	for(i = 1;i<=N;i++){
		while(!que[i].empty()){
			curWindow[i] += time[que[i].front()];
			comp[que[i].front()] = curWindow[i];//写入完成的时间
			que[i].pop();//将队首元素出队 
		}
	}
	
	for(i = 1;i<=Q;i++){	
		int startTime = comp[query[i]] - time[query[i]];//表示顾客的开始处理时间
		if(startTime >= 540) cout <<"Sorry\n";
		else printRes(comp[query[i]]);			
	}
} 

4.测试用例

2 2 7 5
1 2 6 4 3 534 2
3 4 5 6 7

2 2 4 4
1 2 6 4
1 2 3 4


1 2 4 4
1 2 6 4
1 2 3 4

1 2 4 4
1 2 597 4
1 2 3 4

3 2 4 4
1 2 540 4
1 2 3 4

5.坑点

这里的坑点主要有:

5.1 题意的理解

Note that since the bank is closed everyday after 17:00, for those customers who cannot be served before 17:00, you must output Sorry instead.

这句话的意思是:
如果对于不能在17:00之前处理的顾客,将会输出Sorry。那么意思就是对于在17:00之前处理,但是服务时间超过了17:00的顾客,还是应该服务到底的,对应在程序中就应该输出一个时间。

5.2 如何实现一个二维队列

见我的博文链接:C++中如何创建一个二维的队列?