1017. Queueing at Bank (25)

来源:互联网 发布:音乐相册 软件 编辑:程序博客网 时间:2024/06/06 14:52

1017. Queueing at Bank (25)

时间限制
400 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

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 (<=10000) - 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 307:55:00 1617:00:01 207:59:59 1508:01:00 6008:00:00 3008:00:02 208:03:00 10
Sample Output:
8.2

类型:模拟

题目大意:有n个客户,k个窗口。已知每个客户的到达时间和需要的时长(不超过60min,超过的会被压缩成60min),如果有窗口就依次过去,如果没有窗口就在黄线外等候(黄线外只有一个队伍,先来先服务),求客户的平均等待时长。银行开放时间为8点到17点,再8点之前不开门,8点之前来的人都要等待,在17点后来的人不被服务。

(1)自己写的

/*1、注意这里时间间隔统一换算成秒,而不是分钟,因为转换成分钟中间要除以60,数值会损失,降低精度这个问题很重要,之前就是因为这个问题最后一个案例无法通过。2、如果客户到达的时间比队列结束的早,需要等待,队列时间为上次上次服务时间加上这次服务时间3、如果客户到达的时间比队列结束的晚,则不需等待,队列结束时间为客户到达时间加上服务时间 4、如果在8点前来的,就需要等到8点。如果17点以后来的,则不会被服务,无需考虑。 */#include<iostream>#include<algorithm>using namespace std;struct node{int hh;int mm;int ss;int time;//所需秒数 int come;//到达时间,统一用秒表示 }peo[10001];int endtime[101];//表示每个队列的出队时间 int cmp(const node &a,const node &b){if(a.hh!=b.hh)return a.hh<b.hh;else if(a.mm!=b.mm)return a.mm<b.mm;elsereturn a.ss<b.ss;}int n,k;int sumtime=0;//总的延迟秒数 int main(){//freopen("in.txt","r",stdin);cin>>n>>k;for(int i=0;i<n;++i){scanf("%d:%d:%d %d",&peo[i].hh,&peo[i].mm,&peo[i].ss,&peo[i].time);peo[i].come=3600*peo[i].hh+60*peo[i].mm+peo[i].ss;if(peo[i].time>60)//不能超过一小时 peo[i].time=3600;elsepeo[i].time*=60;//转换成秒 }sort(peo,peo+n,cmp);fill(endtime,endtime+101,28800);//数组初始化 int index=0;//记录参加平均时间计算的人数 for(int i=0;i<n;++i){if(peo[i].come>61200)//17:00之后来的,后面及其自己不考虑 break;int early=endtime[0];int best=0;++index; for(int j=1;j<k;++j){if(endtime[j]<early){early=endtime[j];best=j;}}if(endtime[best]>peo[i].come)//如果来的时间比队列结束时间还迟,等待时间为0 {sumtime+=endtime[best]-peo[i].come;endtime[best]+=peo[i].time;}else//来的时间比结束的迟,则排队的结束时间需要更新(***重要***) endtime[best]=peo[i].come+peo[i].time;}if(index>0)printf("%.1f",sumtime/index/60.0);else cout<<"0.0";return 0;} 

(2)别人的不错代码

分析:客户结构体node,里面有come为到达时间和time为需要服务的时长。先将所有满足条件的(到来时间点在17点之前的)客户放入数组中,数组的长度就是需要服务的客户的个数。window数组表示某个窗口的结束时间,每一个客户到来的时候,选择最早结束时间的窗口,如果最早结束时间比他还早,那么他一来就能被服务,更新window的值;如果最早结束时间比他晚,他需要等待,累加等待的时间,然后更新window的值。
一开始所有窗口的值都为8点整。对所有客户要先进行排序,按来的时间的早晚排序,之后再先来先服务。因为涉及分钟和秒数,可以把所有时间暂时先化解成秒数的形式,便于计算。如果一个可以被服务的客户都没有,需要直接输出0.0,因为任何数除以0都没有意义。

#include <cstdio>#include <vector>#include <algorithm>using namespace std;struct node {    int come, time;} tempcustomer;bool cmp1(node a, node b) {    return a.come < b.come;}int main() {    int n, k;    scanf("%d%d", &n, &k);    vector<node> custom;    for(int i = 0; i < n; i++) {        int hh, mm, ss, time;        scanf("%d:%d:%d %d", &hh, &mm, &ss, &time);        if(time > 60)            time = 60;        int cometime = hh * 3600 + mm * 60 + ss;        if(cometime > 61200)            continue;        tempcustomer.come = cometime;        tempcustomer.time = time * 60;        custom.push_back(tempcustomer);    }    sort(custom.begin(), custom.end(), cmp1);    vector<int> window(k, 28800);    double result = 0.0;    for(int i = 0; i < custom.size(); i++) {        int tempindex = 0, minfinish = window[0];        for(int j = 1; j < k; j++) {            if(minfinish > window[j]) {                minfinish = window[j];                tempindex = j;            }        }        if(window[tempindex] <= custom[i].come) {            window[tempindex] = custom[i].come + custom[i].time;        } else {            result += (window[tempindex] - custom[i].come);            window[tempindex] += custom[i].time;        }    }    if(custom.size() == 0)        printf("0.0");    else        printf("%.1f", result / 60.0 / custom.size());    return 0;}

(3)

#include<stdio.h>  #include<vector>  #include<algorithm>  using namespace std;  struct Time{   int hour;   int minute;   int second;  };//时间结构体  int turn2sec(Time T){   return T.hour * 60 * 60 + T.minute * 60 + T.second;  }//把时间化为秒  struct Customer{   int s_time;   int server_time;   bool operator < (const Customer &A)const{    return s_time < A.s_time;   }//顾客结构体,以及比较函数,按到达的先后  }buf[10002];  int ans[10002];//存储各个顾客的等待时间  int queue[102];//队伍,存储顾客编号  int main(void){   //freopen("F://Temp/input.txt", "r", stdin);   int N, K;   while (scanf("%d%d", &N, &K) != EOF){    Time tmp;    for(int i = 0; i < N; i ++){     scanf("%d:%d:%d", &tmp.hour, &tmp.minute, &tmp.second);     buf[i].s_time = turn2sec(tmp);     int server;     scanf("%d", &server);     buf[i].server_time = server * 60;    }    sort(buf, buf + N);    for (int i = 0; i < K; i++){     queue[i] = -1;    }    for (int i = 0; i < N; i++){     ans[i] = -1;    }//初始化    int count = 0;    for (int t = 28800; t <= 864000 && buf[count].s_time <= 61200; t++){//为了应对五点前有顾客开始服务,但是结束的时间超过五点,所以这里的t设置的很大     for (int i = 0; i < K; i++){      if (queue[i] != -1){       int tmp = queue[i];       if ((buf[tmp].s_time + ans[tmp] + buf[tmp].server_time) == t){//如果到达时间+等待时间(即开始时间)+服务时间==当前时间,则出对        queue[i] = -1;       }      }     }     for (int i = 0; i < K; i++){      if (queue[i] == -1 && t >= buf[count].s_time){        queue[i] = count;//如果队伍有空,并且当前时间大于顾客的到达时间,则入队        ans[count] = t - buf[count].s_time;//并计算等待时间        count++;      }     }    }    int sum = 0;    int i;    for (i = 0; i < N; i++){     if (ans[i] == -1)break;     else{      sum += ans[i];     }    }    if (i == 0)printf("0/n");    else printf("%.1f\n", (double)sum / i / 60);   }   return 0;  }  
(4)其实更好的办法的用窗口来,王道的代码如下:这里可以看到,王道的代码中是直接找出下一个可用的时间点,然后累加到等待时间总和中,这样它的时间是跳着来的,肯定要比按时间一秒一秒增加得要快得多。

#include <stdio.h>   #include <string.h>   #include <algorithm>   using namespace std;      int N,K,wait_time=0;   struct Customer   {       int arrive_time;       int need_time;   };      struct Customer customer[10002];      struct Windows   {       int next_available_time;   };//特别得,窗口结构体,里面是当前顾客的结束时间,也就是窗口下一次空闲的时间      struct Windows windows[102];      bool cmp(struct Customer a,struct Customer b)   {       return a.arrive_time<b.arrive_time;   }      int find_available_windows(int arrive_time)   {       int i;       for(i=0;i<K;i++) {           if(windows[i].next_available_time<=arrive_time) {               return i;           }       }       return -1;   }//找到空闲的窗口      int find_earliest_window()   {       int i;       int e=0;       for(i=1;i<K;i++) {           if(windows[i].next_available_time<windows[e].next_available_time) {               e=i;           }       }       return e;   }//找到最早的空闲窗口      int main()   {       scanf("%d%d",&N,&K);       int i;       char arrive_time[20];       int need_time;       for(i=0;i<K;i++)           windows[i].next_available_time=3600*8;//都先初始化为8点       int len=0;       for(i=0;i<N;i++) {           int h,m,s;           scanf("%s%d",arrive_time,&need_time);           if(strcmp(arrive_time,"17:00:00")>0)               continue;                      sscanf(arrive_time,"%d:%d:%d",&h,&m,&s);           if(h<8)               wait_time+=8*3600-(3600*h+60*m+s);//把所有八点前的顾客到八点的时间都累计,当作都是八点到的           customer[len].arrive_time=3600*h+60*m+s;           customer[len++].need_time=need_time*60;       }       N=len;          sort(customer,customer+N,cmp);          for(i=0;i<N;i++) {           int w=find_available_windows(customer[i].arrive_time);           if(w>=0) {//找到空闲窗口           //    windows[w].next_available_time=customer[i].arrive_time+customer[i].need_time;               if(customer[i].arrive_time<8*3600) {                   windows[w].next_available_time=8*3600+customer[i].need_time;               } else {                   windows[w].next_available_time=customer[i].arrive_time+customer[i].need_time;               }           } else { //找不到空闲窗口               w=find_earliest_window();           /*    wait_time+=windows[w].next_available_time-customer[i].arrive_time;          *    windows[w].next_available_time=(windows[w].next_available_time-customer[i].arrive_time)+customer[i].need_time;          */               if(customer[i].arrive_time<8*3600) {//如果到得早 窗口的下个可用时间等于当前下个可用时间加新来顾客所需要服务时间                   wait_time+=windows[w].next_available_time-8*3600;                   windows[w].next_available_time=windows[w].next_available_time+customer[i].need_time;               } else {                   wait_time+=windows[w].next_available_time-customer[i].arrive_time;                   windows[w].next_available_time=windows[w].next_available_time+customer[i].need_time;               }                              }       }          printf("%.1f\n",1.0*wait_time/60.0/N);   }