Проблемы с динамическим программированием
У меня возникли трудности с пониманием динамического программирования, поэтому я решил решить некоторые проблемы. Я знаю основные динамические алгоритмы, такие как самая длинная общая подпоследовательность, проблема рюкзака, но я знаю их, потому что я их читаю, но я не могу придумать что-то самостоятельно: - (
например, мы имеем подпоследовательность натуральных чисел. Каждое число, которое мы можем взять с плюсом или минусом. В конце мы берем абсолютное значение этой суммы. Для каждой подпоследовательности найти наименьшее возможное результат.
in1: 10 3 5 4; out1: 2
in2: 4 11 5 5 5; out2: 0
in3: 10 50 60 65 90 100; out3: 5
объяснение для 3-го: 5 = |10+50+60+65-90-100|
что хуже, мой друг сказал мне, что это простая проблема рюкзака, но я не вижу никакого рюкзака здесь. Является ли динамическое программирование чем-то сложным или только у меня с ним большие проблемы?
3 ответов
как было указано amit, этот алгоритм может быть понят как экземпляр проблема раздела. Для простой реализации взгляните на этот код:
def partition(A):
n = len(A)
if n == 0:
return 0
k, s = max(A), sum(A)/2.0
table = [0 if x else 1 for x in xrange(n*k)]
for i in xrange(n):
for j in xrange(n*k-1, -1, -1):
if table[j-A[i]] > table[j]:
table[j] = 1
minVal, minIdx = float('+inf'), -1
for j in xrange(int(s)+1):
if table[j] and s-j < minVal:
minVal, minIdx = s-j, j
return int(2*minVal)
при вызове с одним из входов в вопрос:
partition([10, 50, 60, 65, 90, 100])
вернет 5
, как ожидалось. Для полного понимания математики решения, пожалуйста, взгляните на это примеры и нажмите на ссылку" сбалансированный раздел".
рюкзак здесь weight = value = number
для каждого элемента.
ваша связь W
is 1/2 * sum(elements)
.
идея в том, что вы хотите максимизировать количество чисел, которые вы "выбираете", не проходя предел 1/2 * sum(elements)
, который точно ранец с value=weight
.
эта проблема на самом деле проблема раздела, что является частным случаем подмножество сумма проблема.
проблема раздела говорит: "Возможно ли получить подмножество элементов, которое суммируется ровно наполовину?"
вывод к вашей проблеме отсюда прост - если есть, возьмите их как +
, и те, которые вы не приняли как -
, а вы out = 0
. [другой способ работает так же]. Таким образом, описанная вами проблема-это оптимизация для задачи раздела.
Это та же проблема, что и в перетягивании каната, без ограничения сбалансированных размеров команды (что не имеет значения): http://acm.uva.es/p/v100/10032.html
Я решил эту проблему с помощью подхода "сверху вниз". Он работает над ограничением, что существует верхний предел для заданных чисел. У вас есть верхний предел или числа не ограничены? Если они не ограничены, я не вижу, как решить это с помощью динамического программирования.