題意
有K個人需要辦理業務,總共有n個窗口,每個窗口後面有一條黃線,窗口和黃線之間只能容納m個人,黃線後面的人只排成一列,如果一旦前面排隊的隊伍有空位,那麼就選擇人數最少的一列,如果人數最少的一列有多種情況,就選擇窗口最短的
思路
首先肯定是要用隊列的,可以利用隊列開成數組解決,我們每次掃描隊列頭,把隊列頭部人完成所需要消耗的時間,加上這個隊列前面所有已經出隊的時間,就是這個人出隊伍的時間,我們掃描隊首出隊伍時間最短的,如果有多個,就選窗口號最小的,這樣能保證這個人是最早出隊的,那麼在黃線外的人,肯定是去這個出隊人所在的隊伍。這樣一直模擬就可以了。
坑點
Sorry的輸出是指的是17點以後沒到窗口的,不要理解爲17點以後離開隊列的。
反思
1題意開始,最後又一個地方沒有讀清楚,導致輸出有問題
2最開始實現想的太複雜,應該多想使得問題簡單化,不熟悉的東西就不要用。
3優先隊列嵌套pair<int,int> 默認是首先第一個關鍵字從大到小,然後是第二個關鍵字從大到小
代碼
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<vector>
#define LL long long
#define pii pair<int,int>
#define mp make_pair
using namespace std;
const int INF = 0x3f3f3f3f;
queue<int>que[24];
int line[25][1006];
int top[25];
int pre[24];
int n,m,k,qq;
int a[300004];
int ans[300005];
int sz[25];
int main(){
#ifdef ONLINE_JUDGE
#else
freopen("in.txt","r",stdin);
#endif
while(~scanf("%d%d%d%d",&n,&m,&k,&qq)){
int tmp;
for (int i=1;i<=n;i++){
while(que[i].size())que[i].pop();
}
memset(pre,0,sizeof(pre));
for (int i=1;i<=k;i++){
scanf("%d",&a[i]);
}
int tot=0;
for (int j=1;j<=m;j++){
for (int i=1;i<=n;i++){
tot++;
if (tot>k)break;
que[i].push(tot);
}
}
int flag=0;
while(flag==0){
int minn=INF;
int w=INF;
int pos=0;
for (int i=1;i<=n;i++){
if (que[i].size() && pre[i]+a[que[i].front()]<minn){
minn=pre[i]+a[que[i].front()];
w=a[que[i].front()];
pos=i;
}else if (que[i].size() && pre[i]+a[que[i].front()]==minn && pos>i){
pos=i;
}
}
if (minn!=INF){
if (pre[pos]<540)
ans[que[pos].front()]=pre[pos]+w;
que[pos].pop();
pre[pos]+=w;
if (tot<k){
tot++;
que[pos].push(tot);
}
}else{
flag=1;
}
}
while(qq--){
scanf("%d",&tmp);
int h=(ans[tmp]/60+8)%24;
int mins=ans[tmp]%60;
if (ans[tmp]!=0){
printf("%02d:%02d\n",h,mins);
}else{
printf("Sorry\n");
}
}
}
return 0;
}