1014 Waiting in Line (30 分)

问题描述:N<20个窗口,每个窗口最多M<10人,K<1000个顾客,Q<1000个查询;前N个人开始时间都是8:00;已知每一个人的处理时间,求每个人的事情办理完的时间。

解题思路:给每个窗口设置一个队列,初始化前N*M(或K)个人,事件驱动为一个人最先处理完,然后将下一个人添加到该窗口的队列中。具体思路为:给每个窗口设置当前顾客完成交易所需的时间t[i],选择t[i]中最小的值,完成一次更新(完成的窗口更新为该队列下一个顾客的处理时间,其他窗口全部减去该值)

AC代码:

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
#define INF 0x0fffff
#define CLOSE 17*60
vector<int>window,dealtime,process;
queue<int>winque[20];
int N,M,K,Q,T=8*60;
bool update(int v)
{
    int i,m=INF,k=0,close=0;
    for(i=0;i<N;++i){//选择每个窗口里处理时间最小的窗口
        if(winque[i].size()){
            if(dealtime[winque[i].front()]<m){
                m=dealtime[winque[i].front()];k=i;
            }
        }else ++close;
    }
    if(close==N)return 1;
    else{
        for(i=0;i<N;++i){//更新所有窗口当前处理时间
            if(winque[i].size()){
                dealtime[winque[i].front()]-=m;
            }
        }
        //if(T<CLOSE)dealtime[winque[k].front()]=T+m;//错在这,本来是17:00之前插入的,一个处理时间可能分为了很多片段,导致完成时超过了CLOSE
        //else if(T==CLOSE&&m==0)dealtime[winque[k].front()]=T;
        //else dealtime[winque[k].front()]=-1;
        T+=m;
        dealtime[winque[k].front()]=T;
        if(T-process[winque[k].front()]>=CLOSE)dealtime[winque[k].front()]=-1;//处理之前超过17:00
        winque[k].pop();
        if(v<K){//后面还有人
            scanf("%d",&dealtime[v]);
            process[v]=dealtime[v];
            if(T<CLOSE)winque[k].push(v);//未关门
            else dealtime[v]=-1;
        }
        return 0;
    }
}
int main()
{
    freopen("test.txt","r",stdin);
    scanf("%d %d %d %d",&N,&M,&K,&Q);
    ++K;
    dealtime.resize(K);process.resize(K);
    int i,j,k,t;
    for(i=0,k=1;i<M&&k<K;++i){//前M*N个人排好队
        for(j=0;j<N&&k<K;++j,++k){
            winque[j].push(k);
            scanf("%d",&process[k]);
            dealtime[k]=process[k];
        }
    }
    while(1){
        if(update(k))break;//更新,
        else ++k;
    }
    while(Q--){
        scanf("%d",&t);
        if(dealtime[t]>0)printf("%02d:%02d\n",dealtime[t]/60,dealtime[t]%60);
        else printf("Sorry\n");
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值