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