題目鏈接:https://www.patest.cn/contests/pat-a-practise/1014
題目大意:銀行有N個窗口,每個窗口前的黃線內最多排隊M個人,有K個人要去辦理業務,每個人要辦理的時間已知。排隊的規則跟現實生活中的排隊類似,黃線內沒有位置的時候,在線外候着;黃線內有位置的時候,選擇隊列最短的去排隊,若有兩個隊長度相同,則選擇隊列序號小的排入。最後計算每個人辦理完結束的時間。
解題思路:
每個人用結構體表示,分量有要接受服務的時間serve;離開的時間leave,爲便於計算,用分鐘表示,最後再進行轉換.
N個窗口,用N個隊列來表示.
customer[i].leave=open[windowindex]+customer[i].serve.其中open[windowindex],windowindex表示該人所在窗口的序號;open[windowindex]爲該人開始辦理時的時間,該時間又等於上一個離開的時間,即當前人的open[windowindex]=customer[i-1].leave;下一個人的open[windowindex]=cusomer[i].leave
確定每個人應該選擇哪個窗口時有兩種情況:
1.黃線內的部分:每個人的窗口號爲p%N
2.黃線的外的人比較複雜。判斷黃線外的人的窗口好的時候,選擇所有隊列中隊頭的人離開時間最早的那個隊排入
代碼如下:
#include <iostream>
#include <queue>
#include <cstdio>
#include <vector>
using namespace std;
struct person
{
int serve,leave;//要接受服務的時間,離開的時間
};
int main(int argc, char const *argv[])
{
int N,M,K,Q;
cin>>N>>M>>K>>Q;
person curstomers[K];//共k個人
/*輸入每個人接受服務的時間*/
for(int i=0;i<K;i++)
cin>>curstomers[i].serve;
vector<queue<int>> window(N);//共N個窗口
int open[N]={0};//每個窗空閒出來的時間初試化爲0
/**先把黃線內的人離開時間確定下來**/
int p;//
for(p=0;p<M*N&&p<K;p++){
curstomers[p].leave=open[p%N]+curstomers[p].serve;//該顧客結束的時間爲當前窗口空閒出的時間+需要服務的時間
open[p%N]=curstomers[p].leave;//該空閒下來的時間爲該顧客離開的時間
window[p%N].push(p);//p放入該窗口的隊列中
}
/*開始確定等在黃線外的人的離開時間*/
while(p<K){
/*每個人都每次從三個窗口的隊頭選一個離開時間最短的入隊,
也就是最短的隊*/
int minleave=curstomers[window[0].front()].leave;
int minwin=0;
for(int i=1;i<N;i++){
if(minleave>curstomers[window[i].front()].leave){
minwin=i;
minleave=curstomers[window[i].front()].leave;
}
}
/*找到隊伍之後開始入隊*/
window[minwin].pop();//服務好的人出隊
window[minwin].push(p);
curstomers[p].leave=open[minwin]+curstomers[p].serve;
open[minwin]=curstomers[p].leave;
p++;
}
/*開始查詢*/
int no;
for(int i=0;i<Q;i++){
cin>>no;
if(curstomers[no-1].leave-curstomers[no-1].serve>=540)
printf("Sorry\n");
else
printf("%02d:%02d\n",8+curstomers[no-1].leave/60,curstomers[no-1].leave%60);
}
return 0;
}