【PAT甲级题解记录】1014 Waiting in Line (30 分)

【PAT甲级题解记录】1014 Waiting in Line (30 分)

前言

Problem:1014 Waiting in Line (30 分)

Tags:模拟 双端队列

Difficulty:剧情模式 想流点汗 想流点血 死而无憾

Address:1014 Waiting in Line (30 分)

问题描述

银行有N个业务窗口,每个窗口可以排队M人,如果有多的人就在外面等,8点开始K个人按照输入顺序去办理业务,当外面等的人能进去排队时优先选择人少的队伍,如果一样就优先选择序号靠前的窗口。现在给定所有人的业务需要的时间,求每个人按照这个规则办完业务的时间。(只接受17点前开始办理的业务,坑点在于17点前办理的业务结束时间可能超过17点,所以输出时不能只判断结束时间还应考虑开始时间

解题思路

  1. 除了有一个坑点外这道题还是一道并不特别复杂的模拟题,由于是排队自然能想到利用队列去解决,这里可以使用双端队列方便队伍头部的处理。
  2. 思路是按照题目意思先初始化所有队列,包括N个双端队列(窗口排队队列)和一个在外面等的队列;
    • 每次循环都从N个队列的队头中确定出还需办理业务的最短时间,在这一次循环里,等于这个最短时间的所有队头客户都能解决业务,这些客户直接保存好时间后出队;
    • 剩余的队头客户则把各自剩余的办理时间减去前面求出来的最短时间,即更新正在办理业务的客户的剩余时间。
    • 一次循环结束后检查外队列,不为空则按照题目规则入窗口排队队列。
  3. 由于输出时需要知道每一个客户的编号,所以队列元素不仅仅是 “int” ,而应该是一个 “pair<int,int>”。
  4. 输出时需要判断开始时间是否超时,需要我们输入时根据客户编号存放业务时间,每个客户的业务结束时间减去这个时间就是开始时间。

参考代码

/*
 * @Author: Retr0.Wu 
 * @Date: 2022-02-16 15:08:36 
 * @Last Modified by: Retr0.Wu
 * @Last Modified time: 2022-02-16 20:35:23
 */
#include <bits/stdc++.h>
using namespace std;
int main()
{
    int N, M, K, Q;
    cin >> N >> M >> K >> Q;
    deque<pair<int, int> > deq[21];
    queue<pair<int, int> > que;
    vector<int> time(K, 0);
    vector<int> time_len(K, 0);
    for (int i = 0; i < K; i++)
    {
        int ktime;
        cin >> ktime;
        time_len[i] = ktime;
        if (i < N * M)
        {
            deq[i % N].push_back(make_pair(i, ktime));
        }
        else
        {
            que.push(make_pair(i, ktime));
        }
    }
    int sumtime = 0;
    for (int i = 0; i < K; i++) // 至多K次,可能更少
    {

        int minn = 0x3f3f3f3f;
        for (int j = 0; j < N; j++)
        { // 遍历每一个柜台
            if (deq[j].empty())
                continue;
            int last = deq[j].front().second;
            minn = min(last, minn);
        }
        sumtime += minn; // 别忘了更新已流逝的时间
        for (int j = 0; j < N; j++)
        {
            if (deq[j].empty())
                continue;
            int last = deq[j].front().second;
            int id = deq[j].front().first;
            last -= minn;  // 该客户剩余业务时间
            if (last == 0) // 该客户业务可以在此次遍历完成
            {
                time[id] = sumtime; // 该客户业务完成
                deq[j].pop_front();
                if (!que.empty())
                {
                    deq[j].push_back(que.front());
                    que.pop();
                }
            }
            else // 该客户业务不可以在此次遍历完成
            {
                deq[j].pop_front();
                deq[j].push_front(make_pair(id, last));
            }
        }
    }
    // for(int i=0;i<K;i++){
    //     cout<<i+1<<" : "<<time[i]<<endl;
    // }
    for (int i = 0; i < Q; i++)
    {
        int id;
        cin >> id;
        if (time[id - 1] - time_len[id - 1] >= 540)
        {
            cout << "Sorry" << endl;
        }
        else
        {
            printf("%02d:%02d\n", 8 + time[id - 1] / 60, time[id - 1] % 60);
        }
    }
    return 0;
}

总结

queue deque stack 等基础数据结构需要熟悉,模拟题一般都用的上。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值