比较好的思路如下:
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int K=1004,N=22;
int cost[K],done[K],sum[N],n,m,k,q;
queue<int>que[N];
void conduct(){
int i=0;
for(;i<n*m &&i<k;++i){
sum[i%n]+=cost[i]; done[i]=sum[i%n];
que[i%n].push(i);
}
for(;i<k;++i){
int th;
for(int mmin=1<<30,j=0;j<n;++j)
if(done[que[j].front()]<mmin)
mmin=done[que[th=j].front()];
sum[th]+=cost[i]; done[i]=sum[th];
que[th].pop(); que[th].push(i);
}
}
int main(){
cin>>n>>m>>k>>q;
for(int i=0;i<k;++i) cin>>cost[i];
conduct();
while(q--){
int no;cin>>no;--no;
if(done[no]-cost[no]>=540) printf("Sorry\n");
else printf("%02d:%02d\n",8+done[no]/60,done[no]%60);
}
}
在这种方式中,最早出队的那个队列并非累计服务时间最少的那个队列。
比较坏的思路如下
#include<vector>
#include<climits>
#include<iostream>
#include<list>
using namespace std;
const int N=1003;
int use[N],leave[N],serve[N],n,m,k,q,outline,lastleavetime;
struct node{int left,id;node(int a,int b):id(a),left(b){}};
typedef list<node> window;
int main(){
cin>>n>>m>>k>>q;
for(int i=0;i<k;++i)cin>>use[i];
vector<window>que(n);
while(outline<k && outline<n*m){
que[outline%n].emplace_back(outline,use[outline]);
outline++;}
// find a man next to leave,and make him leave,refresh the lefttime in que,and make
// the one outline to wait in line,if any.
while(true){
int mmin=INT_MAX,nth=-1;
for(int i=0;i<n;++i)
if(que[i].size() &&que[i].front().left<mmin)
mmin=que[nth=i].front().left;
if(nth==-1)break;
auto x=que[nth].front();
que[nth].pop_front();
leave[x.id]=lastleavetime+x.left;
lastleavetime=leave[x.id];
if(que[nth].size())
serve[que[nth].front().id]=lastleavetime;
mmin=INT_MAX;int nth2=-1;
for(int i=0;i<n;++i)
if(que[i].size()){
if(i!=nth)
que[i].front().left-=x.left;
if(que[i].size()<mmin)
mmin=que[nth2=i].size();
}//if(que[..
if(outline<k) {que[nth2].emplace_back(outline,use[outline]);outline++;}
}//while(true)
while(q--){
int nth;cin>>nth;--nth;
if(serve[nth]>=540)printf("Sorry\n");
else printf("%02d:%02d\n",8+leave[nth]/60,leave[nth]%60);
}//while(q--..
}