PAT 甲级 1017 Queueing at Bank (25 分)

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

需要维护的是服务窗口,用个“优先队列”进行维护。里面存放的是“本窗口空闲的时刻” 

后面排队的人,不需要维护,只需要用结构体数组存储,按照到达时间排个序,然后遍历

算法:

存储三个窗口的“优先队列”,初始化存入三个8.00, 接着遍历后面排队的人。
若到达时刻>=窗口空闲时刻 (即优先队列的队首,最早空闲的窗口)
        =>此人无需等待,total不变;pop队首,push(此人到达时间+服务时间) 
若到达时刻<窗口空闲时刻 
        =>total+=窗口空闲时刻-到达时刻;push(窗口空闲时刻+服务时间)

好像普通队列也行,就是始终要维护队列大小顺序。貌似优先队列可以自动维护  

这是我第一次写真正带点数据结构知识的题目。之前自己实现链表搞得魔怔了,上来看到,诶,后面有人排队,不多说,刚好队列还没写过,先把队列造出来。然后就自己手写链队列,纯纯的nt。

不管有多兴奋,先把所有思路理清楚再动笔吧。这次真是惨痛教训。要维护的对象都弄错了。

写题时,能用c++的库就用,貌似那些基本数据结构类型,都有预定义,用就完事了。自己写弄半天,效果说不定还不好。

 

#include<bits/stdc++.h>
using namespace std;

//后面排队的人; 
struct peo{
	//没必要时分秒都写进去,输出与其无关。写得多看的烦,输入的时候转化一下就行。 
	//到达秒数 
	int ari;
	//等待秒数 
	int wat;
};

bool cmp(peo a,peo b)
{
	return a.ari<b.ari;
}

int main()
{
	//人数 窗口数
	int np,nw;
	//优先队列(升序),具体使用看收藏夹; 
	priority_queue< int,vector<int>,greater<int> > q;
	
	//排队的人 
	peo p[10001];
	cin>>np>>nw;
	//由于17.00之后到达的人无需排队直接走人,因此,如果将他们存入p数组中,排序就会带来问题。
	//np记录的是总人数,npp记录的是有效人数。 
	int npp=np;
	for(int i=0;i<npp;)
	{
		int h,m,s,w;
		scanf("%d:%d:%d %d",&h,&m,&s,&w);
		if(3600*h+60*m+s>61200) 
		{
			//超过17.00,有效人数--; 
			npp--;
			continue;
		}
		p[i].ari=3600*h+60*m+s;
		p[i].wat=60*w;
		i++;
		//cout<<p[i].ari<<"   "<<p[i].wat;
	}
	//sort默认从小到大排序;
	//cmp返回为真,则顺序不变,否则交换。->return a>b 降序 
	//如果我们想从大到小排序可以将cmp参数写为greater<int>()就是对int数组进行排序   
	sort(p,p+npp,cmp);
	
//	for(int i=0;i<npp;i++){
//		cout<<p[i].ari<<"  "<<p[i].wat<<endl;
//	}
	
	//初始化窗口,初值为8.00
	for(int i=0;i<nw;i++)
	{
		q.push(28800);
	}
	
	//算法
	int total=0;
	for(int i=0;i<npp;i++)
	{
		//ww为 最先闲置出来的窗口的 闲置时刻 
		int ww=q.top();
		q.pop();
		//到达时间早于闲置时刻 
		if(p[i].ari<ww){
			total+=ww-p[i].ari;
			q.push(ww+p[i].wat);
		}
		//到达时间晚于或等于空闲时刻,则无需等待
		else{
			q.push(p[i].ari+p[i].wat); 
		} 
	} 
	printf("%.1f",total/60.0/npp);
}
 


貌似用到了STL容器,虽然之前搜过,但是还是基本完全不懂。以后再补一下c++里面的东西。

最大的收获是,优先队列,用在这题上简直完美。

优先和普通队列不同的就在于我们可以自定义其中数据的优先级, 让优先级高的排在队列前面,优先出队

优先队列具有队列的所有特性,包括基本操作,只是在这基础上添加了内部的一个排序,它本质是一个实现的

参考到了:1017. Queueing at Bank (25)-PAT甲级真题(模拟)_柳婼 の blog-CSDN博客

        优先队列的使用方法

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值