1. 程式人生 > >pat 1017. Queueing at Bank (模擬優先佇列)

pat 1017. Queueing at Bank (模擬優先佇列)

好久沒有做pat了,重新開刷

本想從這道水題入手可以快點,結果卻慘遭滑鐵盧,到第二天才全部通過

廢話說完看題,模擬題,模擬的是多視窗排隊。

建議把時間統一轉化為秒做處理。

我選擇了用map儲存依次到達的顧客(題設保證了到達時間都不相同),用priority_queue模擬視窗業務過程。

以顧客為程式的演進標度,即迴圈遍歷map,相機對優先佇列做操作。

在初始階段進隊直到到達視窗人數後,始終保持優先佇列中元素數量一出一進。

在到達時間小於實際開始服務時間的顧客入隊時,累加其等待時間。

值得注意的是,雖然這種方法一定程度與事實是不符合的(eg:新元素進隊時可能實際上不止一箇舊元素應當出隊),但這並不影響對時間的計算。

point:視窗數可能多於17:00前的顧客數,此時直接輸出0.0即可

優先佇列預設是最大元素出隊,可以過載也可以寫比較函式,我是將其轉化為負數處理的。

#include<stdio.h>
#include<map>
#include<queue>
using namespace std;
int main()
{
	int n,k,i,t,time,t1,t2,free,wait,current,count;
	char s[10];
	int tt[10005];
	scanf("%d %d",&n,&k);
	t1=8*60*60;
	t2=17*60*60;
	map<int,int> m;
	map<int,int>::iterator p;
	priority_queue<int> q;
	wait=0;
		
	if(n<=0||k<=0)
	{
	  printf("0.0\n");
	  return 0;
	}
	
	for(i=0;i<n;i++)
	{
		scanf("%s %d",&s,&t);
		time=((s[0]-'0')*10+(s[1]-'0'))*60*60+((s[3]-'0')*10+(s[4]-'0'))*60+((s[6]-'0')*10+(s[7]-'0'));
		if(t>60)
			t=60;
		if(time<=t2)
		{
			m.insert(make_pair(time,t*60));
		}
	}
	
	free=k;
	current=t1;
	p=m.begin();
	count=m.size();

	if(count<=k)
	{
	  printf("0.0\n");
	  return 0;
	}
	
	while(p!=m.end())        
	{
		if(free>0)
		{
			while(free>0&&p!=m.end())
			{  
				--free;
				if(p->first>=current)
				{
					q.push(-p->first-p->second);
				}
				else
				{ 
					wait+=current;
					wait-=p->first;
					q.push(-current-p->second);			
				}
				++p;
			}
		}
		else if(!q.empty())
		{
			current=-q.top();
			q.pop();
			++free;
		}		
	}
	
	double ans = double (wait);
	ans/= (count*60.0);	   
	printf("%.1lf\n",ans);
	return 0;
}


錯誤記錄:

本來把所有8:00前到達的顧客的到達時間都標度為8:00然後置於multimap中。

但無法通過第一個case

最後發現這個做法實際上破壞了8:00前到達的顧客的到達先後順序,當8:00前到達的顧客的到達時間數量多於視窗數時,其先後順序就會影響整體的等待時間

看來是對STL容器的屬性有所遺忘所導致的錯誤

以上