Подтвердить что ты не робот

Как разбить список элементов на равные разделы в соответствии с весом элемента?

У меня есть список элементов, который выглядит примерно так:

[
  ["orange", 9],
  ["watermelon", 3],
  ["grapefruit", 6],
  ["peach", 8],
  ["durian", 2],
  ["apricot", 6]
]

Я хотел бы разбить этот список на... сказать две группы, чтобы сумма весов элементов в каждой группе была как можно более одинаковой, т.е.:

List 1:
  orange: 9
  durian: 2
  apricot: 6
  TOTAL: 17

List 2:
  watermelon: 3
  grapefruit: 6
  peach: 8
  TOTAL: 17

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

Это работает нормально, но у него есть недостатки. Я думаю, что второй проход по группам, в которых я обмениваюсь элементами между ними, приведет к более равномерно распределенным группам, но вовлеченный код может стать слишком сложным.

Знает ли кто-нибудь более эффективный или разумный способ сделать это?

Спасибо!

4b9b3361

Ответ 1

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

Раздел методов этой статьи содержит несколько способов приблизительного или псевдополиномиального решения. В частности, если вы можете жить с приблизительным ответом, вы можете попробовать жадный подход:

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

Время выполнения этого подхода - O(n^2), и оно гарантированно поможет вам в пределах 4/3 от точного решения.

Если у вас должно быть точное решение, а ваш набор данных достаточно мал, вы всегда можете использовать метод грубой силы, генерирующий каждую возможность (это экспоненциально, O(2^n)). В зависимости от ваших требований к производительности, этого может быть достаточно.

Ответ 2

Вы можете суммировать все веса, делиться на количество групп, придумывать целевой вес, а затем перебирать предметы в порядке убывания веса, бросая их в ту же группу, если они подходят под или под целевым весом, и в другую группу, если они этого не делают.

Вероятно, есть некоторые математики, которые могут придумать официальное доказательство того, как это сделать, но это была моя мысль с головы.

Ответ 3

Это не сработает. Например, S = {5, 5, 4, 3, 3}.