Reputation: 493
I'm trying to convert the following recursive code to bottom up/iterative Dynamic Programming. However I cannot figure out the order in which I should iterate as the states depend on next and previous index.
matrix = [[-1, 4, 5, 1],
[ 2,-1, 2, 4],
[ 3, 3,-1, 3],
[ 4, 2, 1, 2]]
rows = len(matrix)
cols = len(matrix[0])
cache = {}
def maxsum(dir, x, y):
key = (dir, x, y)
if key in cache: return cache[key]
base = matrix[y][x]
if x < cols-1:
best = base + maxsum(2, x+1, y)
else:
best = base
if dir != 0 and y > 0:
best = max(best, base + maxsum(1, x, y-1))
if dir != 1 and y < rows-1:
best = max(best, base + maxsum(0, x, y+1))
cache[key] = best
return best
Is it possible to convert this code to iterative? If yes, help me out with the ordering for iterations.
'dir' can take value from 0-2.
x and y will be between 1 and 1000.
I don't want to use stack to solve this. I want to solve this using general iterative loops like the way we do in bottom up dynamic programming.
Upvotes: 2
Views: 168
Reputation: 20518
The general idea is to imagine the recursive call graph/tree and what the leaf nodes are; then, the iterative solution is simply going from the leaf nodes and iteratively build the tree, all the way to the root.
Of course, this is easier said than done, but often there is structure to the problem that can help in your intuition. In this particular case, this is the 2D grid.
Let's start by building some intuition. Look at the branches in the code. They decide whether you recurse in a particular circumstance. What do they correspond to? When do you not recurse? In order, these are:
We need to build these first.
Ask yourself: in what circumstances do we not recurse at all? This is the base case. In no particular order, these are:
dir=1
dir=0
Finally, ask yourself: starting with the values that we have, what can we calculate?
dir=1
dir=0
From this, we can then calculate the entire right edge for dir=2
.
Now that we've filled the values for the right edge, what can we then calculate? Remember the special circumstances above. The cells that only depend on the right edge are the two cells in the top and bottom edges immediately to the left of the right edge, with dir=1
and dir=0
, respectively.
With that in hand, we can now calculate the second column from the right for dir=1
and dir=0
, and therefore dir=2
.
Repeat until you find the value for the cell you wanted.
Note: this is a little suboptimal because it fills the entire table, but it should suffice to illustrate the idea.
def fill(dir, x, y):
base = matrix[y][x]
if x < cols-1:
best = base + cache[2, x + 1, y]
else:
best = base
if dir != 0 and y > 0:
best = max(best, base + cache[1, x, y - 1])
if dir != 1 and y < rows - 1:
best = max(best, base + cache[0, x, y + 1])
cache[dir, x, y] = best
def maxsum(dir, x, y):
for i in range(cols - 1, -1, -1):
for j in range(rows - 1, -1, -1):
fill(0, i, j)
for j in range(rows):
fill(1, i, j)
for j in range(rows):
fill(2, i, j)
return cache[dir, x, y]
Upvotes: 1