pat 甲级A1014 Waiting in Line (30分)

题目链接:

https://pintia.cn/problem-sets/994805342720868352/problems/994805498207911936

 

题目大意:

此题和patA1017在题目假设上是一致的,都是涉及K个顾客到银行中N个窗口的排队问题,其中,排队原则是:每个窗口即,队列最多一次可排N名顾客,且如果一旦入队则无法变动队列。当N个窗口没满时,当前第一个即将入队的人都会选择人数最少的队列,当存在多个相同长度的最短队列,则从编号最小的开始;已知银行的营业时间为早上八点到下午五点,因此如果某一顾客的开始服务时间为下午五点或者之后,则无法被服务。依次给出这K个顾客需要服务的时间,以分钟为单位,然后给出需要查询的顾客编号,输出对应顾客的结束服务时间,无法被服务,则输出sorry。需要注意的是,与patA1017不同的是,K个顾客已经按编号1~K排好序。

这是一个排队问题,那么显然需要设置N个窗口队列。

用两个int型数组ans,need分别保存对应编号的服务结束时间,以及服务时间。变量poptime记录队列队首顾客的结束时间,变量endtime记录队列队尾顾客的结束时间,初始化为早上八点,同时,需要设置队列q保存队伍中顾客的信息。设置结构体pnode保存窗口信息。为了省去时间进制转换的麻烦,不妨将时间转换成以分钟为单位的数值。

 

参考代码:

#include <cstdio>
#include <queue>
#include <algorithm>
#include <vector>

using namespace std;
const int maxn = 1010;
int n, m, k, query, q;
int ans[maxn], need[maxn];

int convert(int h, int m){
    return h*60 + m;
}

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

int main(){
    int pos = 0; //当前第一个未入队编号
    scanf("%d %d %d %d", &n, &m, &k, &query);
    vector <Pnode> window(n);
    for(int i = 0; i < k; i++){  //读入服务时间
        scanf("%d",&need[i]);
    }
    for(int i = 0; i < n; i++){ //初始化每个窗口的endtime以及poptime;
       window[i].endtime = window[i].poptime = convert(8, 0);
    }
    for(int i = 0; i < min(n*m, k); i++){ //循环入队,此时因为窗口前存在未满的队列,
        window[pos%n].q.push(pos);          //则以此入队列即可,需要更新队伍顾客信息q,
        window[pos%n].endtime += need[pos];    //以及队伍结束时间
        if(pos < n) window[pos].poptime = need[pos];      //若此顾客为当前队列第一个时,
                                                //还需要更新队首的结束时间
        ans[pos] = window[pos%n].endtime;  //将编号为pos的顾客结束服务时间加入ans数组中。
        pos++;
    }
    for(; pos < k; pos++){
        int idx = -1, minpoptime = 1e9;   //找出队首顾客最早结束服务的队列。
        for(int i = 0; i < n; i++){
            if(window[i].poptime < minpoptime){
                idx = i;
                minpoptime = window[i].poptime;
            }
        }
        Pnode& W = window[idx];
        W.q.pop();           
        W.q.push(pos);            //将当前顾客入队,更新endtime以及poptime
        W.endtime += need[pos];
        W.poptime += need[W.q.front()];
        ans[pos] = W.endtime;
    }
    for(int i = 0; i < query; i++){     //服务开始时间即 结束服务时间-服务时间
        scanf("%d", &q);
        if(ans[q - 1] - need[q - 1] >= convert(17, 0)) printf("Sorry\n");
        else printf("%02d:%02d\n",ans[q-1]/60, ans[q - 1]%60);
    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值