演習8.3シングルウィンドウの「クランプされた」バージョンのバンクキューイング問題(30ポイント)
「目詰まり」をキューに入れることは、強い不満を引き起こす行動ですが、この現象はしばしば存在します。銀行の単一ウィンドウのキューイングの問題で、銀行にサービスを提供するウィンドウが1つしかなく、すべての顧客が到着時間に応じて長いキューに配置されているとします。ウィンドウが空くと、次の顧客はトランザクションを処理するためにウィンドウに移動します。このとき、後ろのi番目の顧客とj番目の顧客が仲良しで、その友人の業務を喜んで処理することがわかっている場合、i番目の顧客のトランザクション処理時間は彼自身の事務のオフィスと友人のオフィスの合計によって費やされた時間。この場合、お客様の待ち時間に影響が出る場合があります。全員が銀行に到着したときに、空のウィンドウがない場合は、トップの友人(ウィンドウでサービスを受けている友人を含む)の助けを求めると仮定します。複数の友人が顧客に助けを求めた場合、顧客は友人に基づいてトランザクションを順番に処理するリクエストの順序を決定します。この現象をシミュレートし、顧客の平均待機時間を計算するプログラムを作成してみてください。
例:
#include <iostream>
#include <cstdio>
#include <vector>
#include <unordered_map>
#include <list>
using namespace std;
struct Customer {
string name;
int T;
int P;
int id;
};
unordered_map<string, int> circle;
vector<Customer> customer;
vector<int> wait;
list<Customer*> queue;
int main()
{
int N, M;
cin >> N >> M;
circle.reserve(N);
for (int i = 0; i < M; i++) {
string name;
int L;
cin >> L;
for(int j = 0; j < L; j++) {
cin >> name;
circle.insert(make_pair(name, i+1));
}
}
customer.resize(N);
wait.resize(N);
for(int i = 0; i < N; i++) {
cin >> customer[i].name >> customer[i].T >> customer[i].P;
customer[i].id = circle[customer[i].name];
queue.push_back(&customer[i]);
}
int last_finish = 0;
for(int i = 0; i < N;) {
Customer *c = queue.front();
int id = c->id;
if(last_finish < c->T) last_finish = c->T;
if(id == 0) {
wait[i++] = last_finish - c->T;
last_finish += min(c->P, 60);
cout << c->name << endl;
queue.pop_front();
} else {
for(auto x = queue.begin(); x != queue.end(); ++x) {
if((*x)->T > last_finish) break;
if((*x)->id != id) continue;
wait[i++] = last_finish - (*x)->T;
last_finish += min((*x)->P, 60);
cout << (*x)->name << endl;
x = queue.erase(x);
--x;
}
}
}
double sum = 0;
for(auto &x : wait) sum += x;
printf("%.1f\n", sum/N);
return 0;
}
アイデア:
最新の終了時間を使用して、同じサークル内の次の友達が最新の終了時間内に到着したかどうかを確認し、到着した場合は処理を続行します。
サークルがない場合は、通常のチームリーダーとして扱われます。