假设有n
热线电话。
每当客户致电热线时,该呼叫就会被转接到其中一条n
线路。我想将呼叫百分比分配给n行中的每行。假设有两条线路,一条线路分配了60%,另一条线路分配了40%,呼叫总数为10,因此第一行将收到6个呼叫,第二行将收到4个呼叫。
我知道提前拨打每条线路的百分比,但是问题是我不知道一天会收到多少次电话。
如何在不知道总呼叫数的情况下分配呼叫数?
假设有n
热线电话。
每当客户致电热线时,该呼叫就会被转接到其中一条n
线路。我想将呼叫百分比分配给n行中的每行。假设有两条线路,一条线路分配了60%,另一条线路分配了40%,呼叫总数为10,因此第一行将收到6个呼叫,第二行将收到4个呼叫。
我知道提前拨打每条线路的百分比,但是问题是我不知道一天会收到多少次电话。
如何在不知道总呼叫数的情况下分配呼叫数?
Answers:
对已经接听的电话进行簿记,并计算它们在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%的情况下,您会看到订购行1跟第二行,因为-10 %小于10%。因此,第1行将接听电话。
我强烈建议使用插入排序,因为它在数组已被多数排序时性能最佳。
另外,作为次要优化,如果您跟踪到目前为止的总呼叫数,而不必计算每条线路的实际百分比,则只需计算该行的总呼叫数减去该行的预期百分比即可线路乘以呼叫总数(delta = t_i-p_i * T)。在这种情况下,增量只是达到预期百分比的呼叫次数的负数。
我希望这可以澄清任何其他疑问。
O(n)
是您可以期望使用插入排序对已经排序的列表进行排序的方法,并且它O(n)
是查找最小值所需的方法。我只是假设已排序。
这是一个幼稚的解决方案,不做任何假设,但允许基于百分比的分配。该解决方案可以通过许多方式加以改进,但这是其要旨。我不确定这是否是您要寻找的东西,但是它将为您带来真正的分布。
伪代码...
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