每日两道算法题-|Day14 of PAT--|1017 Queueing at Bank (25point(s))--|结构体排序--|运算符重载 详解

1017 Queueing at Bank (25point(s))

Suppose a bank has K windows open for service. There is a yellow line in front of the windows which devides the waiting area into two parts. All the customers have to wait in line behind the yellow line, until it is his/her turn to be served and there is a window available. It is assumed that no window can be occupied by a single customer for more than 1 hour.

Now given the arriving time T and the processing time P of each customer, you are supposed to tell the average waiting time of all the customers.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 numbers: N (≤104​​ ) - the total number of customers, and K (≤100) - the number of windows. Then N lines follow, each contains 2 times: HH:MM:SS - the arriving time, and P - the processing time in minutes of a customer. Here HH is in the range [00, 23], MM and SS are both in [00, 59]. It is assumed that no two customers arrives at the same time.

Notice that the bank opens from 08:00 to 17:00. Anyone arrives early will have to wait in line till 08:00, and anyone comes too late (at or after 17:00:01) will not be served nor counted into the average.

Output Specification:

For each test case, print in one line the average waiting time of all the customers, in minutes and accurate up to 1 decimal place.

Sample Input:

7 3
07:55:00 16
17:00:01 2
07:59:59 15
08:01:00 60
08:00:00 30
08:00:02 2
08:03:00 10

Sample Output:

8.2


题目意思很简单,有家银行,每天早八点开门,晚五点下班,来的早的和来时柜台有人的都需要等候,超过五点一分钟及以后的等都不用等,直接麻溜回家,明儿再来吧。
试问除了明儿再来的那几个人,今天这几个顾客的平均等待时间

输入:
先告诉你顾客人数,然后告诉你服务窗口的人数
接下来将每个顾客的到店时间和所需服务的时间告诉你

输出:
直接输出平均每个顾客等待时间即可


Attention:

  • 因为注意到时间的最小单位是秒,所以此题中的等待时间用秒作为单位,最后再进行转化

Details:

定义时间结构体来存放时间,并重载赋值操作符和小于号操作符

typedef struct Time{
    int hour;
    int min;
    int sec;
    Time(int h, int m, int s): hour(h), min(m), sec(s){}
    Time(): hour(), min(), sec(){}
    Time& operator =(const Time &t){
        this->hour=t.hour;
        this->min=t.min;
        this->sec=t.sec;
        return *this;
    }
    bool operator <(const Time &t){
        if(this->hour!=t.hour)  return this->hour<t.hour;
        else if(this->min!=t.min)   return this->min<t.min;
        else return this->sec<t.sec;
    }
}Time;

然后定义一个结构体–record,用来存放每个顾客的信息

typedef struct record{
    Time t;
    int pro_t;
}record;

然后从键盘读入信息,并将信息填入一个个record中去,除去到达时间在五点一分及以后的顾客以外,其余顾客按顺序入队,然后按照时间顺序进行排序

在之后的时间比较中,由于需要将当前顾客进店时间与当前几个窗口最早结束时间进行比较,于是定义一个容器用来存放各个窗口当前服务结束时间:

vector< Time > win;

并按照题意进行初始化,初始化为早八点:

	for(int i=0;i<winNum;i++){
        Time temp(8,0,0);
        win.push_back(temp);
    }

以后对于每个顾客,只要找出当前几个窗口中结束时间最早的:

		int flag=-1;
        Time temp(80,0,0);
        for(int j=0;j<win.size();j++){
           if(win[j]<temp){
               temp=win[j];
               flag=j;
           }
        }

然后将这个最早结束的时间与自己的进店时间进行比较,进行等待时间的计算操作以及相应更新操作:

如果最早结束时间晚于进店时间,那么当前窗口结束时间调用add_t()函数更新为:最早结束时间加上当前顾客服务事件之后的时间点;等待时间加上通过调用subtrac()函数得到的时间差即可:

	   if(que[i].t<win[flag]){
          total+=subtrac(win[flag],que[i].t);
          add_t(win[flag],que[i]);
       }
       

如果最早结束时间早于进店时间,那么当前窗口结束时间调用swap_t()函数更新为,当前顾客进店时间加上当前顾客服务时间之后的时间点;等待时间不做操作:

 		else{
          swap_t(win[flag],que[i]);
        }

最后,输出平均等待时间即可。


Code:

#include <bits/stdc++.h>
using namespace std;
int winNum, cusNum;
double total=0.0;
typedef struct Time{
    int hour;
    int min;
    int sec;
    Time(int h, int m, int s): hour(h), min(m), sec(s){}
    Time(): hour(), min(), sec(){}
    Time& operator =(const Time &t){
        this->hour=t.hour;
        this->min=t.min;
        this->sec=t.sec;
        return *this;
    }
    bool operator <(const Time &t){
        if(this->hour!=t.hour)  return this->hour<t.hour;
        else if(this->min!=t.min)   return this->min<t.min;
        else return this->sec<t.sec;
    }
}Time;
typedef struct record{
    Time t;
    int pro_t;
}record;
vector< record > que;
vector< Time > win;
bool cmp(const record &a, const record &b){
        if(a.t.hour!=b.t.hour) return (a.t.hour<b.t.hour);
        else if(a.t.min!=b.t.min)   return (a.t.min<b.t.min);
        else    return (a.t.sec<b.t.sec);
}
double subtrac(const Time &t1, const Time &t2){
    double cnt=0.0;
    cnt+=t1.sec-t2.sec;
    cnt+=(t1.min-t2.min)*60;
    cnt+=(t1.hour-t2.hour)*60*60;
    return cnt;
}
void add_t(Time &rst, const record &rc){
    for(int i=0;i<rc.pro_t;i++){
        rst.min++;
        if(rst.min==60){
            rst.hour++;
            rst.min=0;
        }
    }
}
void swap_t(Time &rst, const record &rc){
    rst.hour=rc.t.hour;
    rst.min=rc.t.min;
    rst.sec=rc.t.sec;
    for(int i=0;i<rc.pro_t;i++){
        rst.min++;
        if(rst.min==60){
            rst.hour++;
            rst.min=0;
        }
    }
}
int main(){
    cin>>cusNum>>winNum;
    for(int i=0;i<winNum;i++){
        Time temp(8,0,0);
        win.push_back(temp);
    }
    for(int i=0;i<cusNum;i++){
        record temp;
        scanf("%d:%d:%d %d", &temp.t.hour, &temp.t.min, &temp.t.sec, &temp.pro_t);
        if((temp.t.hour>17)||(temp.t.hour==17&&(temp.t.min!=0||temp.t.sec!=0)))  
            continue;
        que.push_back(temp);
    }
    sort(que.begin(), que.end(), cmp);
    for(int i=0;i<que.size();i++){
        int flag=-1;
        Time temp(80,0,0);
        for(int j=0;j<win.size();j++){
           if(win[j]<temp){
               temp=win[j];
               flag=j;
           }
        }
        if(que[i].t<win[flag]){
          total+=subtrac(win[flag],que[i].t);
          add_t(win[flag],que[i]);
       }
        else{
          swap_t(win[flag],que[i]);
        }
    }
    total/=(double)que.size();
    total/=60.00;
    printf("%.1f", total);
    return 0;
}

Summary and harvest

(for my current level)
复习了:

Time(int h, int m, int s): hour(h), min(m), sec(s){}
Time(): hour(), min(), sec(){}

  • 结构体内外实现操作符重载的写法与区别

(此处没有找到好的学习链接,先空着,有空自己写一篇给初学讲一讲)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值