PAT甲级 - 1014 Waiting in Line (银行排队问题 | queue+模拟)

本文介绍了一种算法解决银行窗口排队问题的方法,通过模拟多个窗口并管理等待时间,确保在有限时间内处理完K个人的业务请求,特别关注17:00截止时间的处理策略。实现代码展示了如何利用优先队列找到最短处理时间的客户并更新窗口状态。
摘要由CSDN通过智能技术生成

Link

题意:

银行里由N个窗口,每个窗口前可容纳M个人等待;

N*M之后的人需要在黄线以外等待寻找最短且序号最小的窗口进入等待;

现告诉你K个人办理业务需要的时间time_cost,试问其中Q个人的离开时间为多少。

已知银行8:00开始接待客户,17:00停止接待。

思路:

显而可见,前N*M个人分别按照1~N,1~N……的顺序进入窗口,之后就是黄线内的N*M个人离开一个,黄线外的客户进入该窗口。

设置N个queue模拟N个窗口,定义统一是时间线timeLine,每次寻找N个窗口头部耗时最短的用时minn_cost,将N个窗口头部的用户time_cost都减去该minn_cost(如果当前用户剩余的耗时为0则结束业务处理得到离开时间),再更新N个queue的头部(将耗时为0的用户pop掉)。

坑点:用户在16:59及以前开始处理业务的都能正常离开,而17:00及以后开始的业务才会"Sorry"。

实现代码:

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N = 1e3+10;

int n, m, k, q;
int time_cost[N], time_cost_back[N], cnt, timeLine;

queue<int> que[21];
map<int, string> ans;

string to_time(int idx, int time){
    string res;
    time += 8*60;
    if(time-time_cost_back[idx]>=17*60) return "Sorry";
    if(time/60<10) res += "0";
    res += to_string(time/60)+":";
    if(time%60<10) res += "0";
    res += to_string(time%60);
    return res;
}

int findMin(){
    int minn = INT_MAX, res = -1;
    for(int i = 1; i <= n; i ++){
        if(que[i].size()==0) continue;
        if(time_cost[que[i].front()]<minn){
            minn = time_cost[que[i].front()];
            res = que[i].front();
        }
    }
    return res;
}

void update(){
    for(int i = 1; i <= n; i ++){
        if(que[i].size()==0) continue;
        if(time_cost[que[i].front()]==0){
            que[i].pop();
            if(cnt<k) que[i].push(++cnt);
        }
    }
}

signed main()
{
    cin >> n >> m >> k >> q;
    for(int i = 1; i <= k; i ++){
        cin >> time_cost[i];
        time_cost_back[i] = time_cost[i];
    }
    bool flag = 0;
    for(int i = 1; i <= m; i ++){
        for(int j = 1; j <= n; j ++){
            if(cnt>k){
                flag = 1;
                break;
            }
            que[j].push(++cnt);
        }
        if(flag) break;
    }

    while(true){
        int idx = findMin();
        if(idx==-1) break;
        int del = time_cost[idx];
        timeLine += del;
        for(int i = 1; i <= n; i ++){
            if(que[i].size()==0) continue;
            time_cost[que[i].front()] -= del;
            if(time_cost[que[i].front()]==0){
                ans[que[i].front()] = to_time(que[i].front(), timeLine);
            }
        }
        update();
    }

    while(q--){
        int x; cin >> x;
        cout << ans[x] << endl;
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值