pat 1017. Queueing at Bank (模擬優先佇列)
阿新 • • 發佈:2019-02-08
好久沒有做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容器的屬性有所遺忘所導致的錯誤
以上