1014 Waiting in Line (30 分,附详细注释,逻辑分析)

写在前面
  • 实现思路
    • 结构体封装窗口数据
    • 时间归一化(统一为分钟,技巧性处理
    • S1. 计算、封装总窗口容量。
      • 下标取余窗口个数,并初始化窗口的计数时间、出队时间(结构体、完成时间数组
    • S2. 循环封装剩余队列元素。
      • 循环判断哪个窗口先存在出队元素,窗口插入元素需更新出队时间、结束时间(结构体、完成时间数组
    • S3. 循环打印
      • 判断开始时间是否超过17:00,打印输出相应值
  • 话痨时刻
    • 针对题目,懵逼了很久(间歇性脑短路),,,
    • 度娘并没有给出好的答案,也可能博主太菜,,,
    • 最后,该试题逻辑处理细节较多(时间切换、累计),较为耗费时间、精力(真实考试大概率挂掉)
测试用例
input:
2 2 7 5
1 2 6 4 3 534 2
3 4 5 6 7
output:
08:07
08:06
08:10
17:00
Sorry
样例示意图
  • 一开始没看懂,惭愧
  • 懵逼!琢磨半天没理顺题目
    在这里插入图片描述
  • 窗口模拟图
    在这里插入图片描述
ac代码
#include <cstdio>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std;

/*小时转换分钟函数,归一处理*/
int hh2mm(int h, int m)
{
    return h*60+m;
}
struct Window
{
    /* 窗口当前队伍的最后服务时间/队首客户服务结束时间*/
    int endTime=hh2mm(8, 0), popTime=endTime;
    queue<int> q;
} window[20];

int main()
{
    int n, m, k, query_num, q_ele;
    scanf("%d%d%d%d",&n,&m,&k,&query_num);
    /*服务结束时间, 耗费时间*/
    int finishTimes[k], dualTimes[k];
    /*读入服务需要时间*/
    for(int i=0; i<k; i++) scanf("%d", &dualTimes[i]);

    /* 循环入队 */
    int inx = 0;
    for(int i=0; i<min(n*m, k); i++)
    {
        window[inx%n].q.push(inx);
        /* 更细窗口结束时间 */
        window[inx%n].endTime += dualTimes[inx];
        /* 更新首个客户的完成时间 */
        if(inx<n) window[inx].popTime = dualTimes[inx];
        /* 当前入队客户服务结束时间保存为答案 */
        finishTimes[inx] = window[inx%n].endTime;
        inx++;
    }
    /* 记录窗口队列中下标元素*/
//    queue<int> q0 = window[0].q, q1=window[1].q;
    /* 剩余客户入队 */
    for(; inx < k; inx++)
    {
        int idx = -1, minPopTime = 1 << 30;
        /* 寻找所有窗口最小poptime */
        for(int i=0; i<n; i++)
        {
            if(window[i].popTime < minPopTime)
            {
                idx = i;
                minPopTime = window[i].popTime;

            }
        }
        /* 引用, 下文中用W代替window[idx],行文清晰 */
        /* 不断弹出所有窗口中,耗时最短的首元素,并将后续元素入队 */
        Window& W = window[idx];
        /* push存储窗口队列中下标元素*/
//        if(idx==0) q0.push(inx);
//        else q1.push(inx);

        W.q.pop();
        W.q.push(inx);
        /* 更新该窗口队列的endTime(累计和) */
        W.endTime += dualTimes[inx];
        /* 更新该窗口的popTime(队首元素) */
        W.popTime += dualTimes[W.q.front()];
        /* 客户inx服务结束时间为该窗口endTime */
        finishTimes[inx] = W.endTime;
    }

    /* // 分别打印窗口队列中下标 */
//    int q00 = q0.size(),q11 = q1.size();
//    for(int i=0; i<q00; i++)
//    {
//       printf("%d+", q0.front());
//       q0.pop();
//    }
//    cout << endl;
//    for(int i=0; i<q11; i++)
//    {
//       printf("%d+", q1.front());
//       q1.pop();
//    }
//    cout << endl;


    /* 查询客户编号 */
    for(int i=0; i< query_num; i++)
    {
        scanf("%d", &q_ele);
        /* 服务开始时间达到17:00, 输出sorry*/
        if(finishTimes[q_ele-1] - dualTimes[q_ele-1] >= hh2mm(17, 0))
            printf("Sorry");
        /* 否则输出服务结束时间 */
        else
            printf("%02d:%02d", finishTimes[q_ele-1]/60, finishTimes[q_ele-1]%60);
        if(i<query_num-1) printf("\n");
    }
}
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xsimah

创作不易,感谢客官的打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值