Unable to implement a dynamic programming table algorithm in python

て烟熏妆下的殇ゞ 提交于 2019-12-04 18:12:52
jfs

The code works if you print the solution using 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)

Output

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

Your code is right.

1 = 1 * 1 + 0 * 2, so T[1, 2] is True.

1 = 1 * 1 + 0 * 2 + 0 * 4, so T[1, 3] is True.

As requested in the comments, a short explanation of the algo: It calculates all numbers from 0 to targetsum that can be represented as a sum of (non-negative) multiples of some of the numbers in data. If T[s, i] is True, then s can be represented in this way using only the first i elements of data.

At the start, 0 can be represented as the empty sum, thus T[0, 0] is True. (This step may seem a little technical.) Let x be the 'i+1'-th element of data. Then, the algorithm tries for each number s if it can be represented by the sum of some multiple of x and a number for which a representation exists that uses only the first i elements of data (the existence of such a number means T[s - c * x, i] is True for some c). If so, s can be represented using only the first i+1 elements of data.

As a side note, you don't really need a defaultdict with what you're doing, you can use a normal 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

If you're using J.S. solution, don't forget to change:

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

with:

if T.get((sum - c * x_k, k - 1)):
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!