简体   繁体   English

子集和变化,动态规划

[英]Subset sum variation, dynamic programming

I'm trying to do the classic subset sum problem with the caveat that the sum of the subset should get as close as possible to tgt without exceeding it.我正在尝试解决经典的子集总和问题,但需要注意的是子集的总和应该尽可能接近tgt而不会超过它。 Here is my recurrence which finds how far away the sum of the subset of numbers is from the number, which is working as expected.这是我的递归,它找出数字子集的总和与数字之间的距离,它按预期工作。 The inf is acknowledging that if the sum goes above tgt , we don't want it: inf承认如果总和超过tgt ,我们不想要它:

def targetSum(S, i,  tgt):
    # your code here
    k = len(S)
    #base case
    if tgt < 0:
        return float('inf')
    if i >= k and tgt >= 0:
        return tgt
    else:
        return min(targetSum(S, i+1, tgt-S[i]), targetSum(S, i+1, tgt))

For the memo table, here's the instructions:对于备忘录表,以下是说明:

Memoize your recurrence by using a memo table of the form [(,)] wherein 0≤≤() and 0≤≤.使用 [(,)] 形式的备忘录表记住您的重复,其中 0≤≤() 和 0≤≤。 It may be helpful to add a function lookupMemoTable inside your code to help you handle lookups where <0.在代码中添加 function lookupMemoTable 可能会有所帮助,以帮助您处理 <0 的查找。 Assume that the target satisfies tgt >= 0.假设目标满足 tgt >= 0。

I couldn't figure out the function lookupMemoTable (which is probably my problem), but here's my code so far, which works for some examples (a1 = [1, 2, 3, 4, 5, 10], tgt = 15) but not all (a3= [11, 23, 37, 48, 94, 152, 230, 312, 339, 413], tgt = 457):我无法弄清楚 function lookupMemoTable (这可能是我的问题),但这是我的代码到目前为止,它适用于一些示例(a1 = [1, 2, 3, 4, 5, 10],tgt = 15)但不是全部(a3= [11, 23, 37, 48, 94, 152, 230, 312, 339, 413], tgt = 457):

def memoTargetSum(S, tgt):
    k = len(S)
    assert tgt >= 0
    ## Fill in base case for T[(i,j)] where i == k
    T = {} # Memo table initialized as empty dictionary
    for j in range(tgt+1):
        T[(k,j)] = j
        #print(T[(k,j)], j)
        
    #def lookupMemoTable

    for i in range(k-1, -1, -1):
        for j in range(tgt, -1, -1):
            if T[(i + 1, j)]-S[i] < 0:
                T[(i,j)] = T[(i + 1, j)]
            else:
                T[(i,j)] = T[(i + 1, j)]-S[i]
    print(T)
    return T

Thanks in advance for your help!在此先感谢您的帮助!

I do not think you have to completely change the whole function.我认为你不必完全改变整个 function。 The table is used to store calculations that could be used again later.该表用于存储以后可以再次使用的计算。 You can add the result of each recursive call to your dict .您可以将每个递归调用的结果添加到您的dict If the function is called again with the same input you can simply return the value inside the dict .如果使用相同的输入再次调用 function ,您可以简单地返回dict内的值。 For example, something like this:例如,像这样:

a3 = [11, 23, 37, 48, 94, 152, 230, 312, 339, 413]
tgt = 457

mem = {}

def targetSum(S, i,  tgt):
    k = len(S)
    
    # If calculation with this input is already computed return result from mem
    if (i,tgt) in mem:
        print('used mem')
        return mem[(i,tgt)]
    
    if tgt < 0:
        return float('inf')
    if i >= k and tgt >= 0:
        return tgt
    else:        
        minimum =  min(targetSum(S, i+1, tgt-S[i]), targetSum(S, i+1, tgt))
        
        # Store result of current calculation in mem if needed again later
        mem[(i,tgt)] = minimum
        return minimum
        

targetSum(a3, 0, tgt)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM