請用順序隊列或鏈式隊列來完成本題。
我們大多都有在銀行排隊的經歷,唉,那坑爹的排隊啊!現在就讓我們來算算我們這些客戶平均需要等多久吧。
每天剛開始時銀行會開m個窗口來為我們total個客戶辦理業務,當有客戶需要辦理業務時,先選擇可以辦理業務的窗口,如果有多個窗口可以辦理業務就選擇空閑時間最長的窗口,如果有多個窗口空閑的時間一樣長,則選擇序號小的窗口辦理業務。假設我們每個人來到的時間和辦理業務所需要的時間(為了簡化問題,采用整數表示時間)都知道了。現在請你算算我們平均需要等待多久呢?
【輸入形式】
有多組測試數據,每組數據開始有兩個正整數m(<20)和total(<200),后面有total對整數,對應客戶先后到來的時間以及辦理業務所需的時間。
【輸出形式】
平均等待的時間,保留兩位小數。
【樣例輸入】
2 6 1 3 4 1 5 3 9 2 13 4 13 3
3 14 0 3 2 2 2 4 5 4 7 2 11 3 12 3 12 4 12 1 13 3 15 4 19 1 22 3 23 2
2 5 0 6 0 5 0 6 7 1 7 2
【樣例輸出】
0.00
0.29
1.20
#include<bits/stdc++.h> using namespace std; int m,tot,a,b;//全局變量 template<class T> class Pque{ protected: struct node{ T data; node* next; node():next(NULL){}//以及這里 node.next初始化為NULL 函數體內沒有內容 }; node* head; int Size; //protected類型的內容就是一個結構體指針和一個size public: Pque():Size(0){//構造函數 在這里Size初始化為0 head=new node;//構造函數 head申請了新的節點 } ~Pque(){ head=head->next; while(head) { node* t=head; head=head->next; delete t; } } void push(T t){//插入元素是尾插 node* p=head; for(;p->next&&p->next->data<t;p=p->next); //最最一開始這個for語句也是不執行的,因為head->next=NULL,直接新建node*n //這句話還挺重要的哈 //這里不涉及插隊哈 大家過來的,都是從底下t=a+b都是等了的,只是等到你了辦完工的時間比隔壁也是等了辦完公的時間要早, //所以走的早啊 這是正常的 來得早等了一會辦了一個小時 來的稍稍晚,等了一會,辦一分鍾就完,肯定后者要早出對 //完全不涉及插隊 node* n=new node; n->data=t;n->next=p->next;p->next=n;//這個data存儲的t是辦完一個顧客的業務的時間,就比如你0時開門,8分到,辦一分鍾,data=9 ++Size;//!!!!!!!!!!!!!! } T pop(){//隊列啊 出隊只能是隊首元素出隊 node* p=head->next; head->next=p->next; T t=p->data; delete p;--Size; return t;//T是int類型的元素了 返回個這 } T front(){return head->next->data;} int size(){return Size;}//用函數是因為size是protected類型的 }; int main(){ while(cin>>m){//m是窗口數 Pque<int> win;//這是一個隊列 名字是win cin>>tot;//tot總人數 double wt=0;//waitting time for(int i=0;i<tot;++i){ cin>>a>>b;//a:到達的時間 b:辦理所需時間 while(win.size()&&win.front()<=a)win.pop(); //這個的意思就是 如果你來的時候 有顧客並且最快辦完業務的顧客的時間在你來到銀行之前 //那么出隊那個最快辦理完業務的 這是個while語句 看看能出隊幾個人 這個語句是把所有早的顧客出隊完 //之后根據銀行剩余顧客情況 1.銀行內顧客數<窗口數 直接進棧辦理業務 2.窗口還是滿的,剩下的打頭的顧客走的時間都比你到的時間晚,那就等,執行else語句 if(win.size()<m) win.push(a+b); //最最一開始執行的是這 因為size=0並且head=new head->next=NULL的 所以進棧 //在顧客數<窗口處的時候 永遠是先執行這個if語句不執行上面的for循環 //這個size其實就現在辦公的顧客人數push進去一個 size++ pop出去一個 size-- else{ int k=win.front();//前一個最快(!!!因為是head->next->data)辦完工的時間 wt+=k-a;//你來的早 就得等 win.pop();//它出棧 隊首出棧 win.push(k+b);//在k的基礎上+b==你辦完工的時間 這個時間入棧 } } cout<<fixed<<setprecision(2)<<wt/tot<<endl; } }
orrrrrrrrrrrrrrrrrrrrrrrrrr
可以先看下面的 理下思路
#include<iostream> #include<iomanip> #include<cmath> #include<cstring> #include<stdio.h> #include<malloc.h> using namespace std; int main() { int m, t; while (cin >> m >> t) { //m:辦理業務的銀行窗口數 t:整個過程辦理業務的人數 這一個while循環完 求出了在一個情形下的情況 int a, b; //a:每一個客戶到來的時間 b:該客戶辦理業務的時間 int sum = 0;//辦理業務等待時間 int q[20];//窗口數 上限20個 memset(q,0,sizeof(q));//把該數組所有值先置為0 for (int i = 0; i < t; i++) {//t客人的數量 cin >> a >> b; int cur = 0;//這個代表窗口 要去選出哪個窗口辦理完上一個業務最快 int min = q[0];//// for (int i = 0; i < m; i++) { if (q[i] <min) { min = q[i]; cur = i; } }////從min到這 是找出這幾個窗口最小的時間 下一個客戶到哪個窗口去辦理業務 if (a < q[cur]) { //如果a:到達的時間 比所有的辦理業務結束的時間還要小 那么它就得等 sum就要++了 sum += (q[cur] - a);//q[cur]:最早結束業務的窗口(eg:24) a:到來的時間(eg:19) 那么就得等24-19=5分鍾; q[cur] += b;//那么這個窗口就又添了一個新業務(在這個窗口等肯定就要在這辦啊) 所以這個窗口結束業務的時間就要再加 +b[上一個人走 //新客戶立馬辦 不用加排隊的時間哇] } else { //如果a:到達的時間 比這個q[cur]()小,就是說現在有空余的窗口 那么就直接在這辦理業務了 q[cur] = a + b;//那么這個空余的窗口就有了新業務 結束業務的時間:a+b(假設上一個人辦完業務是5分走的 8分來了新客人 辦理業務3分鍾 //所以這個窗口結束業務的時間8+3=11分鍾) } } printf("%.2f\n", sum*1.0/t);//算完啦輸出 } return 0; }