@Romario21

Алгоритм равномерного распределения заявок?

C#, Java
Товарищи прошу помощи.
Есть список менеджеров с количеством заявок на руках
В систему приходит новая пачка заявок, задача их равномено распределить по менеджерам. Что бы у всех было примерно одинаковое кол-во. В начальный момент у всех менеджеров разное кол-во на руках

Лена - 1
Оля - 10
Иван -35
Сергей - 75


Пример: Пришла новая пачка заявок: 35шт.
Лена - (было)1 + 22(из пачки) = 23(стало)
Оля - (было)10+13(из пачки)=23(стало)
Иван -35
Сергей - 75
  • Вопрос задан
  • 1360 просмотров
Решения вопроса 2
lexxpavlov
@lexxpavlov
Программист, преподаватель
foreach (var newOrder in newOrders)
{
    // ищем минимальное количество заявок среди всех менеджеров
    var minOrdersCount = managers.Min(m => m.Orders.Count);
    // ищем менеджера с найденным количеством (если несколько - берём первого)
    var manager = managers.First(m => m.Orders.Count == minOrdersCount);
    // даём заявку менее занятому менеджеру
    manager.Orders.Add(newOrder);
}

Этот алгоритм не самый быстрый - постоянно ищется сначала количество заявок у всех менеджеров, потом поиск менеджера с минимальным количеством заявок.

Вот алгоритм посложнее, в нём поисков по всем менеджерам происходит меньше (особенно, когда большое количество новых заявок):
class Manager
{
    public string Name { get; private set; }
    public List<int> Orders { get; private set; }

    public Manager(string name, int ordersCount = 0)
    {
        Name = name;
        Orders = ordersCount > 0
            ? Enumerable.Range(1, ordersCount).ToList()
            : new List<int>();
    }
}

static void Main(string[] args)
{
    var managers = new Manager[]
    {
        new Manager("Лена", 1), 
        new Manager("Оля", 10), 
        new Manager("Иван", 35), 
        new Manager("Сергей", 75), 
    };
    var newOrders = Enumerable.Range(1, 35).ToList();
    var newOrdersCount = newOrders.Count;
    var ordersAssigned = 0;

    while (ordersAssigned < newOrdersCount)
    {
        var ordersCounts = managers.Select(m => m.Orders.Count).OrderBy(count => count).Distinct().ToArray();
        var addingOrdersCount = ordersCounts.Length > 1 ? ordersCounts[1] - ordersCounts[0] : ordersCounts.First();
        var managersWithMinOrders = managers.Where(m => m.Orders.Count == ordersCounts[0]).ToArray();
        // нашли менеджеров с минимальным количеством заявок
        if (managersWithMinOrders.Length * addingOrdersCount < newOrdersCount)
        { // заполняем самых незанятых менеджеров до того же уровня занятости
          // т.е. добавляем Лене (10 - 1) = 9 заявок
            foreach (var manager in managersWithMinOrders)
            {
                for (int i = 0; i < addingOrdersCount; i++)
                {
                    manager.Orders.Add(newOrders[ordersAssigned]);
                    ordersAssigned++;
                }
            }
        }
        else
        {
            // незанятых менеджеров нет, заполняем оставшиеся заявки по менеджерам по очереди
            while (ordersAssigned < newOrdersCount)
            {
                var managerIndex = ordersAssigned % managersWithMinOrders.Length;
                managersWithMinOrders[managerIndex].Orders.Add(newOrders[ordersAssigned]);
                ordersAssigned++;
            }
        }
    }

    foreach (var manager in managers)
    {
        Console.WriteLine("{0}: {1} заявок", manager.Name, manager.Orders.Count);
    }
    Console.ReadKey();
}
Ответ написан
Vlad_IT
@Vlad_IT
Front-end разработчик
Если в пачках строгое кол-во заявок, то можно отсортировать эту пачку по убыванию, и итерируя снизу (с большого) давать человеку с минимальным количеством заявок.
UPD: Как-то так получается https://jsfiddle.net/zxhonma2/
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы