排隊“夾塞”是引起大家強烈不滿的行為,但是這種現象時常存在。在銀行的單窗口排隊問題中,假設銀行只有1個窗口提供服務,所有顧客按到達時間排成一條長龍。當窗口空閑時,下一位顧客即去該窗口處理事務。此時如果已知第i位顧客與排在后面的第j位顧客是好朋友,並且願意替朋友辦理事務的話,那么第i位顧客的事務處理時間就是自己的事務加朋友的事務所耗時間的總和。在這種情況下,顧客的等待時間就可能被影響。假設所有人到達銀行時,若沒有空窗口,都會請求排在最前面的朋友幫忙(包括正在窗口接受服務的朋友);當有不止一位朋友請求某位顧客幫忙時,該顧客會根據自己朋友請求的順序來依次處理事務。試編寫程序模擬這種現象,並計算顧客的平均等待時間。
輸入格式:
輸入的第一行是兩個整數:1,為顧客總數;0,為彼此不相交的朋友圈子個數。若M非0,則此后M行,每行先給出正整數2,代表該圈子里朋友的總數,隨后給出該朋友圈里的L位朋友的名字。名字由3個大寫英文字母組成,名字間用1個空格分隔。最后N行給出N位顧客的姓名、到達時間T和事務處理時間P(以分鍾為單位),之間用1個空格分隔。簡單起見,這里假設顧客信息是按照到達時間先后順序給出的(有並列時間的按照給出順序排隊),並且假設每個事務最多占用窗口服務60分鍾(如果超過則按60分鍾計算)。
輸出格式:
按顧客接受服務的順序輸出顧客名字,每個名字占1行。最后一行輸出所有顧客的平均等待時間,保留到小數點后1位。
輸入樣例:
6 2
3 ANN BOB JOE
2 JIM ZOE
JIM 0 20
BOB 0 15
ANN 0 30
AMY 0 2
ZOE 1 61
JOE 3 10
輸出樣例:
JIM ZOE BOB ANN JOE AMY 75.2
代碼:
#include <cstdio> #include <queue> #include <map> using namespace std; struct peo { char name[4]; int T,P; }p[10000]; int ans[10000],c; int n,m,l,num,ptime; double w; int f[10001],vis[10001]; char name[4]; map<string,int> mp; int main() { scanf("%d%d",&n,&m); while(m --) { scanf("%d",&l); for(int i = 0;i < l;i ++) { scanf("%s",name); f[mp[name] = ++ num] = m + 1;//由於不同圈子沒有交集 所以不用並查集 用數組標記是否是同一個圈子 } } for(int i = 0;i < n;i ++) { scanf("%s%d%d",p[i].name,&p[i].T,&p[i].P); if(p[i].P > 60) p[i].P = 60; } int i = 0; while(i < n) { while(i < n && vis[i]) i ++; int d = f[mp[p[i].name]],j = i; if(i >= n) break; do {//這里這個循環是這樣的 如果說第一個人在辦理業務 后邊有朋友 可以同時幫着辦了 所謂等待時間就是從到達到自己的業務被着手處理等的時間 只要第一個人還在辦理 后邊來的朋友都可以交給他處理 除非他走了 if(vis[j] || f[mp[p[j].name]] != d) { j ++; continue; } w += max(0,ptime - p[j].T); ans[c ++] = j; ptime = max(ptime,p[j].T) + p[j].P; vis[j ++] = 1; } while(d && j < n && p[j].T <= ptime); } for(int i = 0;i < n;i ++) { printf("%s\n",p[ans[i]].name); } printf("%.1f",w / n); }