Невозможно реализовать алгоритм таблицы динамического программирования в python - PullRequest
1 голос
/ 10 февраля 2012

У меня проблемы с созданием таблицы в python.По сути, я хочу построить таблицу, в которой для каждого числа будет указано, смогу ли я использовать ее для разбиения другого (это таблица, взятая из принятого ответа в Могут ли алгоритмы грубой силы масштабироваться? ).Вот псевдокод:

for i = 1 to k
    for z = 0 to sum:
        for c = 1 to z / x_i:
            if T[z - c * x_i][i - 1] is true:
                set T[z][i] to true

Вот реализация Python, которую я имею:

from collections import defaultdict


data = [1, 2, 4]
target_sum = 10

# T[x, i] is True if 'x' can be solved
# by a linear combination of data[:i+1]
T = defaultdict(bool)           # all values are False by default
T[0, 0] = True                # base case


for i, x in enumerate(data):    # i is index, x is data[i]
    for s in range(target_sum + 1): #set the range of one higher than sum to include sum itself
        for c in range(s / x + 1):  
            if T[s - c * x, i]:
                T[s, i+1] = True

#query area   
target_result = 1
for node in T:
    if node[0]==target_result:
        print node, ':', T[node]

Итак, я ожидаю, что если target_result установлен на 8, он показывает, как каждый элемент вlist data может использоваться для разбивки этого числа.Для 8, 1,2,4 для всей работы, поэтому я ожидаю, что все они будут правдой, но эта программа делает все правдой.Например, 1 можно разбить только на 1 (а не на 2 или 4), но когда я запускаю его как 1, я получаю:

(1, 2) : True
(1, 0) : False
(1, 3) : True
(1, 1) : True

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

(Примечание: я могу быть совершенно неправ, но я узнал, что defaultdict создает записи, даже если их нет, и если записьсуществует, алгоритм превращает его в истину, может быть, в этом и проблема, я не уверен, но это была мысль, которую я пытался использовать, но она не сработала для меня, потому что, кажется, нарушает общую реализацию) Спасибо!

Ответы [ 3 ]

4 голосов
/ 10 февраля 2012

Код работает, если вы печатаете решение, используя RecursivelyListAllThatWork():

coeff = [0]*len(data)
def RecursivelyListAllThatWork(k, sum): # Using last k variables, make sum
    # /* Base case: If we've assigned all the variables correctly, list this
    # * solution.
    # */
    if k == 0:
        # print what we have so far
        print(' + '.join("%2s*%s" % t for t in zip(coeff, data)))
        return
    x_k = data[k-1]
    # /* Recursive step: Try all coefficients, but only if they work. */
    for c in range(sum // x_k + 1):
       if T[sum - c * x_k, k - 1]:
           # mark the coefficient of x_k to be c
           coeff[k-1] = c
           RecursivelyListAllThatWork(k - 1, sum - c * x_k)
           # unmark the coefficient of x_k
           coeff[k-1] = 0

RecursivelyListAllThatWork(len(data), target_sum)

Вывод

10*1 +  0*2 +  0*4
 8*1 +  1*2 +  0*4
 6*1 +  2*2 +  0*4
 4*1 +  3*2 +  0*4
 2*1 +  4*2 +  0*4
 0*1 +  5*2 +  0*4
 6*1 +  0*2 +  1*4
 4*1 +  1*2 +  1*4
 2*1 +  2*2 +  1*4
 0*1 +  3*2 +  1*4
 2*1 +  0*2 +  2*4
 0*1 +  1*2 +  2*4
2 голосов
/ 11 февраля 2012

Как примечание: вам не нужно defaultdict с тем, что вы делаете, вы можете использовать обычный dict + .get():

data = [1, 2, 4]
target_sum = 10

T = {}
T[0, 0] = True

for i,x in enumerate(data):
    for s in range(target_sum + 1):    # xrange on python-2.x
        for c in range(s // x + 1):
            if T.get((s - c * x, i)):
                T[s, i+1] = True

Если вы используете J.S. Решение, не забудьте изменить:

if T[sum - c * x_k, k - 1]:

с:

if T.get((sum - c * x_k, k - 1)):
2 голосов
/ 10 февраля 2012

Ваш код вправо .

1 = 1 * 1 + 0 * 2, поэтому T [1, 2] равно True.

1 = 1 * 1 + 0 * 2 + 0 * 4, поэтому T [1, 3] равно True.

Как и просили в комментариях, краткое объяснение алгоритма: Он вычисляет все числа от 0 до targetsum, которые могут быть представлены как сумма (неотрицательных) кратных некоторых чисел в data. Если T[s, i] равно True, то s можно представить таким образом, используя только первые i элементы data.

В начале 0 можно представить как пустую сумму, таким образом, T[0, 0] равно True. (Этот шаг может показаться немного техническим.) Пусть x будет «i + 1» -ым элементом данных. Затем алгоритм пытается для каждого числа s, если оно может быть представлено суммой, кратной x, и числом, для которого существует представление, использующее только первые i элементы данных (существование таких число означает T[s - c * x, i], для некоторых c это True). Если это так, s можно представить, используя только первые i+1 элементы data.

...