Проблемы с динамическим программированием

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

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

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

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