0
点赞
收藏
分享

微信扫一扫

PAT_甲级_1014 Waiting in Line (30分) (C++)


目录

​​1,题目描述​​

​​题目大意​​

​​输入​​

​​输出​​

​​2,思路​​

​​存储结构​​

​​ 处理过程​​

​​注意​​

​​队列(头文件:queue)的常用函数:​​

​​3,代码​​

1,题目描述

PAT_甲级_1014 Waiting in Line (30分) (C++)_PAT

PAT_甲级_1014 Waiting in Line (30分) (C++)_模拟类题目_02

Sample Input:

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

 

Sample Output:

08:07
08:06
08:10
17:00
Sorry

题目大意

银行里有N个窗口,每个窗口前有一条黄线,黄线内可容纳M个人,每个黄线之后的人在穿越黄线时,会选择当前排队人数最少的一个窗口,(而且一旦进入黄线内,不再切换窗口),若两个以上的窗口等待人数相等且最短,则选择编号最小的窗口。

输出前来询问的顾客的交易结束时间;

输入

第一行:N:窗口数(<=20),M:黄线内容量(<=10),K:顾客数量(<=1000,编号1-K),Q:询问交易结束时间的顾客数量(<=1000);

第二行:各顾客的交易处理时间;

第三行:询问交易结束时间的顾客编号

输出

给出每位询问顾客的交易结束时间(以HH:MM的形式给出,HH取值[08,17],MM取值[00,59],若交易结束时间晚于17:00,输出Sorry)

2,思路

模拟题(过程及细节较为繁琐,容易出错,但思路简单),队列的应用

 

 

存储结构

  • n:窗口数,m:黄线容纳数,k:顾客数,q:询问的顾客数;
  • queue<int> window[20]:窗口队列,窗口数目不超过20,编号从0开始;
  • int customer[1001][2]:存放顾客的[0]处理需求时间,[1]服务结束时间;
  • int back[1001]:存放顾客的处理需求时间(备份)

 处理过程

  1. 输入顾客相关的数据,并备份;
  2. 填满黄线内的所有窗口。num = n * m < k ? n * m : k;
  3. 若黄线外有顾客,则按照出一个人,进一个人的方法模拟(每出一个人,更新正在处理需求的所有人的处理时间,以及从营业开始到现在的总用时time【用分钟来表示】);
  4. 若黄线外无顾客,则每个窗口计算一次,可直接得出正在排队的所有人的业务处理结束时间;
  5. 输出时,若顾客的服务开始时间早于17:00,但结束时间晚于17:00,仍属于服务区间不输出Sorry,即customer[c][1] - back[c] < 540;

 

注意

  1. 顾客1->窗口0, 顾客2->窗口1, ...... 顾客m->窗口0 ,顾客m+1->窗口1 ;
  2. 顾客的编码从1开始;
  3. printf("%02d:%02d\n", h, m)输出时钟规格(HH:MM:SS)的数据很方便;

队列(头文件:queue)的常用函数:

入队:q.push(x); 将x接到队列的末端。

出队:q.pop(); 弹出队列的第一个元素,注意,并不会返回被弹出元素的值。

访问队首元素:q.front(),即最早被压入队列的元素。

访问队尾元素:q.back(),即最后被压入队列的元素。

判断队列空:q.empty(),当队列空时,返回true。

访问队列中的元素个数:q.size()

 

3,代码

#include<iostream>
#include<queue>
#include<climits>
using namespace std;

int main(){
int n, m, k, q; //n:窗口数,m:黄线容纳数,k:顾客数,q:询问的顾客数
int time = 0; //当前时间已过08:00多少分钟
int index;
scanf("%d%d%d%d", &n, &m, &k, &q);

queue<int> window[20]; //最多有20个窗口
int customer[1001][2]; //最多有1000名顾客(编号从1开始) 存放顾客需求的[0]处理时间和[1]结束时间
int back[1001]; //对游客的问题处理时间进行备份
for(int i = 1; i <= k; i++){ //游客编号从1开始!!!
scanf("%d", &customer[i][0]);
back[i] = customer[i][0];
}

int num = n * m < k ? n * m : k; //先按规则 依次填满黄线内的窗口
index = 1;
while(index <= num){
for(int j = 0; j < n; j++){ //顾客1->窗口0 顾客2->窗口1 ...... 顾客m->窗口0 顾客m+1->窗口1
window[j].push(index);
index++;
}
}

//当黄线之外还有顾客时 一直会有进有出
index = n * m + 1; //当前黄线外第一位顾客的序号
while(index <= k){
int fastWin = 0; //记录窗口中最快结束的那个窗口
int minTime = INT_MAX; //记录当前各个窗口正在处理的客户中 剩余最短时间
for(int i = 0; i < n; i++){
if(customer[window[i].front()][0] < minTime){
minTime = customer[window[i].front()][0];
fastWin = i;
}
}
for(int i = 0; i < n; i++){ //更新正在窗口前处理问题的客户的剩余时间
customer[window[i].front()][0] -= minTime;
}
time += minTime; //总计时累加
customer[window[fastWin].front()][1] = time;
window[fastWin].pop();
window[fastWin].push(index++);

}

//黄线之外无客户 只出不进 可直接计算出各个客户的结束服务时间
for(int i = 0; i < n; i++){ //按顺序依 次计算每个窗口队列中各客户的服务结束时间
int temp = time;
while(window[i].empty() != true){
int x = window[i].front();
window[i].pop();
time += customer[x][0];
customer[x][1] = time;
}
time = temp; //由于是每个队列计算一次 故需要恢复原始的time
}

for(int i = 0; i < q; i++){
int c;
scanf("%d", &c);
if(customer[c][1] - back[c] < 540){ //由于原始数据在计算过程中丢失 故需使用备份back
int h = 8 + customer[c][1] / 60;
int m = customer[c][1] % 60;
printf("%02d:%02d\n", h, m); //学到了!!!
}
else{
printf("Sorry\n");
}
}
return 0;
}

 

举报

相关推荐

0 条评论