目录
💟这里是CS大白话专场,让枯燥的学习变得有趣!
💟没有对象不要怕,我们new一个出来,每天对ta说不尽情话!
💟好记性不如烂键盘,自己总结不如收藏别人!
💌1014和1017这两个排队题真的搞死我了[○・`Д´・ ○],记录一些踩坑点!
🧡1014 Waiting in Line
题目链接:PTA | 程序设计类实验辅助教学平台
解析
💌银行有N个窗口,每个窗口在黄线内可排M个人,如果黄线内没有排满就入队(按窗口顺序入队),排满的话就在黄线外等待,黄线内出一个进一个,如果同时出了多个,选窗口小的进。营业时间8:00-17:00,如果客户在17:00及之后还没被服务,就不再服务,如果已经开始服务了,就要完成服务。
🍠输入
第一行:窗口数N,黄线内每个窗口最大容量M,客户数K,问询结束时间的客户数Q。
第二行:K个客户的处理时间(min)。
第三行:问询的客户编号。
易错点
🍠黄线外选取最小的出列窗口。
🍠查询的时候编号要减一,因为存储的时候索引是从0开始的~
代码
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
struct Customer{
int startTime,processTime,endTime;
}customer[1000];
int main(){
int N,M,K,Q; //N:窗口 M:一队长度 K:总人数 Q:需要告知时间的人
cin >> N >> M >> K >> Q;
for(int i=0;i<K;i++) cin >> customer[i].processTime;
queue<Customer> windows[N];
int openTime = 8*60, closeTime = 17*60;
// 入队
for(int i=0;i<K;i++){
// 排黄线内
if(i<N*M){
int window = i%N;
if(i<N){
customer[i].startTime = openTime;
customer[i].endTime = openTime + customer[i].processTime;
}else{
customer[i].startTime = windows[window].back().endTime;
customer[i].endTime = customer[i].startTime + customer[i].processTime;
}
windows[window].push(customer[i]);
}
// 排黄线外
else{
int window = 0;
for(int j=1;j<N;j++){
if(windows[j].front().endTime<windows[window].front().endTime){
window = j;
}
}
windows[window].pop();
customer[i].startTime = windows[window].back().endTime;
customer[i].endTime = customer[i].startTime + customer[i].processTime;
windows[window].push(customer[i]);
}
}
int id;
while(Q--){
cin >> id;
if(customer[id-1].startTime < closeTime){
printf("%02d:%02d\n",customer[id-1].endTime/60,customer[id-1].endTime%60);
}
else{
cout << "Sorry" << endl;;
}
}
return 0;
}
🧡1017 Queueing at Bank
题目链接:PTA | 程序设计类实验辅助教学平台
解析
💌银行有N个客户,K个窗口,客户来了排成一队,选择空闲窗口服务,没有则继续排队等待,求,求平均等待时长。营业时间8:00-17:00,如果客户8:00之前到,要等到8:00开始服务,如果客户在17:00之后到,就不再为其服务,如果已经到了,加班加点也要完成服务(没见过这么敬业的银行(キ`゚Д゚´)!!)。可以不用队列来做,直接用数组lastTime记录当前每个窗口结束时间即可。
易错点
🍠平均是对有效服务客户的平均,没有被服务的客户不算在内。最好一开始读数据的时候就把不符合的客户剔除,不然后面测试点4一直不通过。。
🍠等待时间的计算要用到达时间和窗口结束时间比较,如果在结束之前到则需要计算,如果在结束之后到则不用等待。
🍠选择当前最快结束或空闲的服务窗口排队,如果需要等待,则该客户结束时间从窗口结束服务时间算起,如果不用等待,则从到达时间算起。
🍠如果没有有效服务,输出0.0。
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
struct Customer{
int time,pro;
int wait = 0;
}cus[10002];
bool cmp(Customer cus1, Customer cus2){
return cus1.time < cus2.time;
}
int main(){
int openTime = 8*60*60, closeTime = 17*60*60;
int N,K; //N:总人数 K:窗口
int success = 0; //记录有效人数
cin >> N >> K;
for(int i=0;i<N;i++){
int hour,min,sec,pro;
scanf("%d:%d:%d %d",&hour,&min,&sec,&pro);
int time = hour*60*60+min*60+sec;
if(time>=closeTime || pro>3600) continue;
cus[success].time = time;
cus[success].pro = pro*60;
success++;
}
sort(cus,cus+success,cmp);
int lastTime[K]; //记录每个窗口当前队伍结束时间
//初始化
for(int i=0;i<K;i++){
lastTime[i] = openTime;
}
for(int i=0;i<success;i++){
//前K个人
if(i<K){
cus[i].wait = max(openTime-cus[i].time,0);
lastTime[i] = max(openTime,cus[i].time)+cus[i].pro;
}
else{
int shortTime = lastTime[0];
int window = 0;
for(int j=1;j<K;j++){
//找当前最短的队伍
if(lastTime[j]<shortTime){
shortTime = lastTime[j];
window = j;
}
}
//排到最短的队伍后面
cus[i].wait = max(lastTime[window]-cus[i].time,0);
//如果等待则从上个人结束时间算起,如果没等则从到达时间算起
lastTime[window] = max(lastTime[window],cus[i].time)+cus[i].pro;
}
}
if(success){
float totalTime = 0;
for(int i=0;i<success;i++){
totalTime += cus[i].wait;
}
float ave = (totalTime/60)/success;
printf("%.1f\n",ave);
}
else printf("%.1f\n",0);
return 0;
}