あると仮定n
ホットラインのためのラインは。
顧客がホットラインに電話をかけるたびに、コールはいずれかのn
回線に転送されます。そして、n行のそれぞれに呼び出しの割合を割り当てたいと思います。2つの回線があり、1つの回線に60%が割り当てられ、もう1つの回線に40%が割り当てられていると仮定します。
各回線への呼び出しの割合は事前にわかっていますが、問題は、1日に受信される呼び出しの数がわからないことです。
総通話数を知らずに通話数を分配するにはどうすればよいですか?
あると仮定n
ホットラインのためのラインは。
顧客がホットラインに電話をかけるたびに、コールはいずれかのn
回線に転送されます。そして、n行のそれぞれに呼び出しの割合を割り当てたいと思います。2つの回線があり、1つの回線に60%が割り当てられ、もう1つの回線に40%が割り当てられていると仮定します。
各回線への呼び出しの割合は事前にわかっていますが、問題は、1日に受信される呼び出しの数がわからないことです。
総通話数を知らずに通話数を分配するにはどうすればよいですか?
回答:
すでにかかってきた通話についていくつかの簿記を行い、n行にわたるそれらの分布を計算します。これにより、nパーセント値(既に達成された分布)が得られ、これを達成したいnパーセントと比較できます。新しいコールが着信するたびに、そのコールをターゲット値からの偏差が最も大きいラインに割り当てます(指定された分布に正確に到達しない限り、これまでにコールが少なすぎるラインが常に存在することに注意してください。ターゲット分布と比較した場合)。
例:最初の呼び出しを1行目に割り当てた後:
total calls line1 total calls line2 perc.line 1 perc. line 2
1 0 100% 0%
*above 60% *below 40% <- next call to 2
1 1 50% 50%
* below 60%: *above40% next to line1
2 1 66% 33%
*above 60% *below 40% <- next to line 2
2 2 50% 50%
* below 60%: *above40% next to line1
3 2 60% 40%
* both hit the mark: next call arbitrary
4 2 66% 33%
*above 60% *below 40% <- next to line 2
4 3 57.1% 42.85%
*below 60% *above 40% <- next to line 1
...
編集:このアプローチは、絶対差を使用せず、すべての偏差の二乗和を最小化する線を選択することにより、さらに改善できます。また、目標値に正確に到達した場合に、より良い結果が得られます。
@DocBrownのソリューションに同意します。アルゴリズム形式に配置する:
for each incoming call:
sort lines ascending by delta* (see footnote below)
// first element in array gets the call
increase number of calls for first element by 1
デルタは、実際のパーセンテージから予想されるラインのパーセンテージを引いた値で決まります。このように、最大の負のデルタを持つものは、予想される割合に適合するために呼び出しを最も必要とするものです。
たとえば、1行目と2行目の予想される割合がそれぞれ60%と40%で、実際の割合が50%と50%の場合、-10 %は10%未満です。したがって、1行目が呼び出しを取得します。
挿入ソートを使用することを強くお勧めします。これは、配列のほとんどがすでにソートされている場合に最高のパフォーマンスが得られるためです。
また、マイナーな最適化として、各回線の実際の割合を計算するのではなく、これまでの合計通話数を追跡する場合は、その回線の合計通話数からその予測通話率を差し引くだけで計算できますlineに呼び出しの総数を掛けます(delta = t_i-p_i * T)。この場合、デルタは単に予想された割合を達成するための負の数の呼び出しです。
それが他の疑問を明らかにすることを願っています。
O(n)
は、既にソートされたリストを挿入ソートでソートできるものでありO(n)
、最小値を見つけるために使用する必要があるものです。ソートされていると思います。
OPが述べた仮定
アルゴリズム設計
各行をその%で定義します
(現在のワーカーの%-ワーカーの割り当てられた%)として定義された0から離れた位置、またはすべての行= 0の場合はランダムな割り当てによって各行をソートします。
各コールを0から離れた最大の回線に転送します
例:それぞれ20、30、50の%の3行。時間xの時点で1人がコールし、すべての回線が0から0離れているため、ランダムに割り当てられます。つまり、すべてのコールの30%を保持する必要がある回線2に割り当てられます。行2はすべてのコールの30%を保持する必要があり、現在はすべてのコールの100%を保持しているため、0からの位置が増加します。次の呼び出し元は、平衡(0)まで1行目または3行目などに割り当てられ、ループが繰り返されます。
これは単純な解決策であり、パーセンテージベースの配布を許可することのみを前提としています。このソリューションは多くの方法で改善できますが、これはその要点です。これがあなたが探しているものであるかどうかはわかりませんが、それはあなたに本当の配布を与えるでしょう。
擬似コード...
int running_total_of_calls = 0
//This is hard coded for clarity. You'd most likely want to dynamically populate this array depending and probably distribute the work by alternating workers. Notice how "worker1" appears 6 out of 10 times in the array.
string[] worker = new string[10]
workers[0] = "worker1"
workers[1] = "worker1"
workers[2] = "worker1"
workers[3] = "worker1"
workers[4] = "worker1"
workers[5] = "worker1"
workers[6] = "worker2"
workers[7] = "worker2"
workers[8] = "worker2"
workers[9] = "worker2"
while(1) //run forever
//This is where the distribution occurs.
//first iteration: 0 modulus 10 = 0.
//second: 1 modulus 10 = 1
//third: 2 modulus 10 = 2
//...
//10th: 10 modulus 10 = 0
//11th: 11 modulus 10 = 1
//12th: 12 modulus 10 = 2
//...
int assigned_number = running_total_of_calls % workers.Count //count of workers array
string assigned_worker = workers[assigned_number]
do_work(assigned_worker)
running_total_of_calls = ++running_total_of_calls