这道题我自己是很没头绪,感觉这种题没什么算法但却很难。

这里有点抽象类的感觉,

1,首先,对于输入的每个人的办事时间,开辟了time[]数组来存储每个人的时间,实际上每个人也只有他的时间信息和下标信息(下标代表他是第几个;

2,struct node {
    int poptime, endtime;
    queue<int> q;
};

int main() {
    int n, m, k, q, index = 1;
    scanf("%d%d%d%d", &n, &m, &k, &q);
    vector<int> time(k + 1), result(k + 1);
    for(int i = 1; i <= k; i++) {
        scanf("%d", &time[i]);
    }
    vector<node> window(n + 1);
    vector<bool> sorry(k + 1, false);

这段代码,实际上抽象出来了柜台这个类,一个柜台有一串排队的队列,有队列的队首和队尾的人办完事情出队的时间,队首的时间可以用来判断下一个即将入队的人是排哪个柜台,队尾的时间???,(我暂时想不出来队尾的时间有什么用,因为一个人挨个办完事,队首的时间叠加起来不就是队尾吗?)同时还创建了一个sorry[],存放最后没时间服务的人。result[index]代表每个人办完事的时间。

3.  for(int i = 1; i <= m; i++) { 
        for(int j = 1; j <= n; j++) {
            if(index <= k) {  //判断是否人都排完了
                window[j].q.push(time[index]);
                if(window[j].endtime >= 540)
                    sorry[index] = true;
                window[j].endtime += time[index];
                if(i == 1)
                    window[j].poptime = window[j].endtime;
                result[index] = window[j].endtime;
                index++;
    }}}

这段代码,总体上说是把当前的n个窗口先都排上一个人,然后n个窗口对应m个队列也给他排满,另外注意整篇代码都需要用index来记录当前这个人的下标。其实这里就体现出endtime的用处了,插入队的时候,如果最后一个人办完事的时候银行都下班了,那这些人都存入sorry数组中去,而不是排队去。  window[j].q.push(time[index]);(这里我对这行代码不是特别理解,q是一个队列,放入时间,差不多是这样存【22 50 70 510】)  if(i ==1 )  window[j].poptime = window[j].endtime;另外这行代码,第一个排进队列的人,那么这个队列的poptime和endtime都是第一个人的时间,(这里我也不理解,好像到这行代码的时候都没有初始化或对poptime与endtime赋值)。其实已经赋值了,上面那行代码执行前已经给endtime赋值了,这行代码就是给poptime赋值,而且也只需要对第一行的poptime赋值 。result[index] = window[j].endtime; index++;这行代码也想了一下,其实这里执行的for循环,每一个人都是一个个排进去的,那么当前这个人排进去前, 已经执行了window[j].endtime += time[index];那么当前这个人办完事的时间就是当前队列的endtime(因为当前排进去的人就是队尾的人)。window[j].q.push(time[index]);这行代码是为第四大步骤做准备工作,因为必须要把每个人的时间保存到队列中,才能在更新队列的时候获取到时间哇。

4到上面那段,算是完成了先把窗口人数排满的工作,接下来还有人没有排上队,就需要判断当前哪个队最先走人,然后去排这个队,并且更新这个队的poptime,endtime。那么怎么具体完成呢?

while(index <= k) { //判断人排完没有,为什么用while,因为这里是一个个排人,
        int tempmin = window[1].poptime, tempwindow = 1;
        for(int i = 2; i <= n; i++) {
            if(window[i].poptime < tempmin) {
                tempwindow = i;
                tempmin = window[i].poptime;
            }
        }  //找出当前最快办完事的窗口,
        window[tempwindow].q.pop(); //当前办完事的窗口的人的时间弹出队列
        window[tempwindow].q.push(time[index]);//把人传入这个办完事的队列
        window[tempwindow].poptime +=  window[tempwindow].q.front();//更新当前这个队列的弹出时间,就是当前队列的第一个人的办事时长,注意是+=,
        if(window[tempwindow].endtime >= 540)//如果超过540
            sorry[index] = true;//加入sorry[]数组。注意上面第二段的时候就有一个加入sorry队列的操作,就是防止前面的几个人办事办太久的情况。
        window[tempwindow].endtime += time[index];//更新endtime
        result[index] = window[tempwindow].endtime;//排到队的人的办完事时间就是endtime,因为他是排在队尾的。
        index++;
    }

5.最后是输出

for(int i = 1; i <= q; i++) {
        int query, minute;
        scanf("%d", &query);//query保存查询的人的下标
        minute = result[query];//查询的人办完事的时间
        if(sorry[query] == true) {//如果在sorry[]中
            printf("Sorry\n");
        } else {
            printf("%02d:%02d\n",(minute + 480) / 60, (minute + 480) % 60);
        }//小时是/60取整,分钟是%60取余。

6思路总结与启发

这类实际问题,要进行抽象化,如本题中,抽象出柜台和顾客。

选好数据结构,这道题首先肯定有queue,因为已经是个排队问题了,哪些数据在输入中要保存,就需要开辟空间,比如sorry,result。

柳神的思路就是这个核心:poptime是为了让黄线外的人可以计算出哪一个队列先空出人来(poptime最小的那个先有人服务完毕),endtime是为了入队后加上自己本身的服务所需时间可以计算出自己多久才能被服务完毕~且前一个人的endtime可以得知自己是不是需要被Sorry(如果前一个人服务结束时间超过17:00,自己当前入队的人就是sorry),还有一个queue表示所有当前该窗口的排队队列。

怎么想出来的呢?那就要根据题意,一步步来想,自然会想到这样做的原因。

而且柳神代码很清晰思路,先排满n个窗口m队,然后如果还有剩余在一个个排。中间还有很多细节问题。做此类题时读懂题意,慢慢想,顺着步骤一步步在草稿纸上写下步骤,遇到问题要想用什么样的数据结构与算法去解决,比如这个人应该被排到哪个队,那就自然想到要比较当前哪个队最先走人,就想到要有个poptime,也要想到这个人加到这个队伍中,他的结束时间是多少,他能不能被服务还能不能加到队伍中,要想到有endtime,以及如何更新这些数据。

pat甲级1014柳神代码解析自学复盘用相关推荐

  1. pat甲级1013图柳神代码解析自学复盘

    1,首先,画个图,很容易弄明白cnt -1 这个道理. 2,我也知道要用dfs,但是代码该怎么写. 3,首先,创建v[1010][1010] 数组来保存两个城市之间是否有没有路(=1) 4,设置boo ...

  2. PAT甲级 1014 刷题记录

    文章目录 一.答案 (一)推荐答案 (二)个人解答 二.坑点 三.相关知识 (一)vector 与queue 两种结构的使用方法 (二)其他 一.答案 (一)推荐答案 链接:PAT甲级1014 测试点 ...

  3. 【PAT乙级】1002 写出这个数——柳神代码解析

    1002 写出这个数 (20 分) 读入一个正整数 n,计算其各位数字之和,用汉语拼音写出和的每一位数字. 输入格式: 每个测试输入包含 1 个测试用例,即给出自然数 n 的值.这里保证 n 小于 1 ...

  4. PAT甲级题目解析和知识点分类整理

    转载请注明出处 个人博客:https://maxusun.github.io/ 今天整理电脑,发现了去年为了考研浙大计算机整理的PAT资料.现在考研已经尘埃落定.想到当时盲目刷题浪费了好多时间,在这里 ...

  5. 2021.9.11周六PAT甲级考试复盘与总结

    周六PAT甲级考试复盘与总结 先说结论:仍未步入"高手"行列:现在的学习节奏与方法是对的,有十万分的必要坚持下去. 题目 知识点 分数 T1 前缀和.二分 11 / 20 T2 排 ...

  6. PAT甲级1060 Are They Equal:[C++题解]字符串处理、有效数字、代码简洁!!!

    文章目录 题目分析 题目链接 题目分析 来源:acwing 分析:字符串处理 题意:把一个数变成0.xxxxx * 10^xxxxx 的形式(小数点后面第一个是大于零的数,除非输入的数本来就是0),位 ...

  7. PAT甲级真题目录(按题型整理)(转自柳神)

    转载自:https://www.liuchuo.net/archives/2502?tdsourcetag=s_pcqq_aiomsg 最短路径 1003. Emergency (25)-PAT甲级真 ...

  8. PAT乙级题目索引(题目+解析+AC代码)

    题目信息 分值 PAT 乙级 1001 害死人不偿命的(3n+1)猜想 15 PAT 乙级 1002 写出这个数 20 PAT 乙级 1003 我要通过! 20 PAT 乙级 1004 成绩排名 20 ...

  9. PAT学习资料汇总(PAT甲级、PAT顶级、PAT考试经验)

    二.PAT甲级 PAT甲级真题目录(按题型整理) PAT甲级真题目录(按题型整理)_love music.的博客-CSDN博客_pat甲级真题 PAT甲[所有题目+解析+代码示例+总结]附带所有历年整 ...

最新文章

  1. 阿里云与WPS深度合作,开放数据处理生态
  2. Mac 安装laravel 框架
  3. 怎么查计算机网络硬件配置,如何查看电脑本机的硬件配置?
  4. iframe的src动态修改并刷新_微服务中配置中心Config+消息总线Bus,实现分布式自动刷新配置
  5. Android HelloWorld 例子
  6. Redis从入门到精通,至少要看看这篇!
  7. c++ 箭头符号怎么打_焊接图纸符号标注图解示例,焊接符号标注实例及方法
  8. P1903-[国家集训队]数颜色/维护队列【带修莫队】
  9. 微信小程序之底部弹框预约插件
  10. 2016/4/22 图形用户界面
  11. Linux下安装Docker,报错docker: unrecognized service的两种解决方案
  12. 第1章 数据可视化概述
  13. Android input监控耳机插入demo
  14. conda安装cv2_『开发技术』Windows极简安装使用face_recognition实现人脸识别
  15. 关于office2016和visio2016无法共存的问题
  16. 中心移动平均_Excel数据分析——移动平均法预测分析
  17. python+django+动态生成word
  18. Linux下用命令行彻底删除文件
  19. python 操作excel(xlsx)进行保存
  20. 战地五多计算机登录账户,玩战地5电脑配置要求

热门文章

  1. 【兔年烟花】旖旎风景——浪漫烟花(Python实现)
  2. Autoware感知瞎学笔记(一)lidar_kf_contour_track
  3. 低版本cad如何打开高版本图纸?不用升级软件也可以搞定
  4. InnoDB与MyISAM的优缺点
  5. Minor GC和Full GC有什么区别?
  6. 资产密集型企业,这么做管理更高效
  7. JetBrains .idea project directory (详细利用教程)
  8. 分享一份完整的软件系统测试方案,建议收藏
  9. 新手操作更换固态和重装系统竟然这么麻烦?!
  10. vmware16下安装ubuntu20.0报错:发生错误,导致虚拟 CPU 进入关闭状态。如果虚拟机外部发生此错误,则可能已导致物理计算机重新启动……