Просматривая ссылки, опубликованные Лоуренсом, я подумал, что попытаюсь что-то поднять. Алгоритм состоит в том, чтобы назначить самый длинный тест кратчайшему списку задач (повторять, пока не будут назначены все тесты). Используя ваши примеры и случайное время тестирования, стандартное отклонение было довольно низким, менее 2 минут при его запуске несколько раз (код на C #, но ничего, что не было бы тривиальным для преобразования):
private static void BuildJobs()
{
PriorityQueue<Task> tasks = new PriorityQueue<Task>();
//create a task list for each node
for (int i = 0; i < 60; i++)
{
Task t = new Task();
tasks.Enqueue(t);
}
//get the list of tests, in order from longest to shortest
int[] testList = new int[2000];
for (int i = 0; i < testList.Length; i++)
{
testList[i] = random.Next(5, 90);
}
Array.Sort<int>(testList);
Array.Reverse(testList);
// add the longest running test to the current shortest task list
foreach (int time in testList)
{
Task t = tasks.Dequeue();
t.addTest(time);
tasks.Enqueue(t);
}
Debug.WriteLine(CalculateStdDev(tasks));
}