简体   繁体   中英

More on dynamic programming

Two weeks ago I posted THIS question here about dynamic programming. User Andrea Corbellini answered precisely what I wanted, but I wanted to take the problem one more step further.

This is my function

def Opt(n):
    if len(n) == 1:
        return 0
    else:
        return sum(n) + min(Opt(n[:i]) + Opt(n[i:])
                            for i in range(1, len(n)))

Let's say you would call

Opt( [ 1,2,3,4,5 ] )

The previous question solved the problem of computing the optimal value. Now, instead of the computing the optimum value 33 for the above example, I want to print the way we got to the most optimal solution (path to the optimal solution). So, I want to print the indices where the list got cut/divided to get to the optimal solution in the form of a list. So, the answer to the above example would be :

[ 3,2,1,4 ] ( Cut the pole/list at third marker/index, then after second index, then after first index and lastly at fourth index). That is the answer should be in the form of a list. The first element of the list will be the index where the first cut/division of the list should happen in the optimal path. The second element will be the second cut/division of the list and so on.

There can also be a different solution:

[ 3,4,2,1 ] 

They both would still lead you to the correct output. So, it doesn't matter which one you printed. But, I have no idea how to trace and print the optimal path taken by the Dynamic Programming solution. By the way, I figured out a non-recursive solution to that problem that was solved in my previous question. But, I still can't figure out to print the path for the optimal solution. Here is the non-recursive code for the previous question, it might be helpful to solve the current problem.

def Opt(numbers):
prefix = [0]
for i in range(1,len(numbers)+1):
    prefix.append(prefix[i-1]+numbers[i-1])
results = [[]]
for i in range(0,len(numbers)):
    results[0].append(0)
for i in range(1,len(numbers)):
    results.append([])
    for j in range(0,len(numbers)):
        results[i].append([])
for i in range(2,len(numbers)+1): # for all lenghts (of by 1)
    for j in range(0,len(numbers)-i+1): # for all beginning
        results[i-1][j] = results[0][j]+results[i-2][j+1]+prefix[j+i]-prefix[j]
        for k in range(1,i-1): # for all splits
            if results[k][j]+results[i-2-k][j+k+1]+prefix[j+i]-prefix[j] < results[i-1][j]:
                results[i-1][j] = results[k][j]+results[i-2-k][j+k+1]+prefix[j+i]-prefix[j]
return results[len(numbers)-1][0]

Here is one way of printing the selected :

I used the recursive solution using memoization provided by @Andrea Corbellini in your previous question. This is shown below:

cache = {}

def Opt(n):
    # tuple objects are hashable and can be put in the cache.
    n = tuple(n)

    if n in cache:
        return cache[n]

    if len(n) == 1:
        result = 0
    else:
        result = sum(n) + min(Opt(n[:i]) + Opt(n[i:])
                              for i in range(1, len(n)))

    cache[n] = result
    return result

Now, we have the cache values for all the tuples including the selected ones.

Using this, we can print the selected tuples as shown below:

selectedList = []
def printSelected (n, low):

    if len(n) == 1:
        # No need to print because it's 
        # already printed at previous recursion level.
        return

    minVal = math.Inf
    minTupleLeft = ()
    minTupleRight = ()
    splitI = 0

    for i in range(1, len(n)):
        tuple1ToI = tuple (n[:i])
        tupleiToN = tuple (n[i:])

        if (cache[tuple1ToI] + cache[tupleiToN]) < minVal:
            minVal = cache[tuple1ToI] + cache[tupleiToN]
            minTupleLeft = tuple1ToI
            minTupleRight = tupleiToN
            splitI = low + i


    print minTupleLeft, minTupleRight, minVal
    print splitI   # OP just wants the split index 'i'.
    selectedList.append(splitI) # or add to the list as requested by OP

    printSelected (list(minTupleLeft), low)
    printSelected (list(minTupleRight), splitI)

You call the above method like shown below:

printSelected (n, 0)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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