Плохая новость: эта проблема является NP-трудной из-за сокращения от подмножества суммы. Для заданных чисел x 1 ,…, x n , S целью суммы подмножества является определение того, является ли некоторое подмножество суммы x i s S. Мы производим A-бутылки емкостью x 1 ,…, x n и B-бутылки емкостью S и (x 1 +… + x n - S) и определить, достаточно ли n заливок.
Хорошая новость: любая жадная стратегия (то есть, выбирайте любую непустую A, выбирайте любую незаполненную B, наливайте до тех пор, пока мы не остановимся) - это 2-аппроксимация (т. Е. Используется не более чем в два раза больше, чем оптимально). Оптимальное решение использует как минимум max (| A |, | B |) заливки, а жадные - не более | A | + | B |, так как каждый раз, когда жадный наливает, либо A сливается, либо B заполняется и не нуждается в разливе или повторении.
Может существовать схема аппроксимации ((1 + ε) -аппроксимация для любого ε> 0). Теперь я думаю, что более вероятно, что есть результат неприемлемости - обычные приемы для получения схем аппроксимации не похоже здесь.
Вот некоторые идеи, которые могут привести к практическому точному алгоритму.
Если дано решение, нарисуйте двудольный граф с левыми вершинами A
и правыми вершинами B
и (ненаправленным) ребром от a
до b
тогда и только тогда, когда a
выливается в b
, Если решение является оптимальным, я утверждаю, что циклов нет - в противном случае мы могли бы устранить наименьшую заливку в цикле и заменить потерянный объем, идущий вокруг цикла. Например, если у меня льется
a1 -> b1: 1
a1 -> b2: 2
a2 -> b1: 3
a2 -> b3: 4
a3 -> b2: 5
a3 -> b3: 6
тогда я могу устранить на a1 -> b1
лей так:
a2 -> b1: 4 (+1)
a2 -> b3: 3 (-1)
a3 -> b3: 7 (+1)
a3 -> b2: 4 (-1)
a1 -> b2: 3 (+1)
Теперь, поскольку на графике нет цикла, мы можем посчитать количество ребер (заливок) как |A| + |B| - #(connected components)
. Единственная переменная здесь - это количество подключенных компонентов, которое мы хотим максимизировать.
Я утверждаю, что жадный алгоритм формирует графики без цикла. Если бы мы знали, каковы были связанные компоненты оптимального решения, мы могли бы использовать жадный алгоритм для каждого и получить оптимальное решение.
Один из способов решения этой подзадачи состоит в том, чтобы использовать динамическое программирование для перечисления всех пар подмножеств X из A и Y из B, таких что sum (X) == sum (Y), а затем передать их в точный алгоритм покрытия. Оба шага, конечно, экспоненциальные, но они могут хорошо работать с реальными данными.