In the grid above, the number of gold coins in each cell is given. Adam needs to start in the bottom-left square and move to the top-right square, moving only up and to the right.
What is the maximum number of gold coins he can collect?
This can be solved using a recursive approach ( dynamic programming ).
coins
), where the bottom-left cell is
(0,0)
and the top-right is
(7,6)
; i.e.,
coins[(1,2)] = 5
.
max_coins
, the maximum number of coins Adam can collect along the way to a given cell, for the first column and row.
max_coins
for the rest of the cells - and
run the code
!
Hint: What are the possible states just before you reach a given cell?
from brilliant import goldgrid coins = goldgrid.grid() height, width = goldgrid.height(coins), goldgrid.width(coins) #Initializing the dictionary for the maximum coins up to a certain cell max_coins = {(0,0) : coins[(0,0)]} #Computing the max_coins values for the first column and row #The maximum coins is the maximum for the cell prior to it, plus the coins in that cell for row in range(1,height): max_coins[(0,row)] = max_coins[(0,row-1)] + coins[(0,row)] for column in range(1,width): max_coins[(column,0)] = max_coins[(column-1,0)] + coins[(column,0)] #Using recursion / dynamic programming to find the remaining maximums for row in range(1,height): for column in range(1,width): max_coins[(column,row)] = #FILL ME IN #Print the maximum value for the top right cell print(max_coins[(width-1,height-1)])
Bonuses:
How can you initialize
max_coins
differently to avoid the separate cases for the first column and row, and just have a single recursive loop? Also, can you modify the code to return the actual path that gives the maximum gold?
This section requires Javascript.
You are seeing this because something didn't load right. We suggest you, (a) try
refreshing the page, (b) enabling javascript if it is disabled on your browser and,
finally, (c)
loading the
non-javascript version of this page
. We're sorry about the hassle.
Am I to weird if I say this problem wasn't hard to crack without programming? Did use a same kind of algorithm on my head though.
Log in to reply
No - I solved it in my head as well.
Log in to reply
Gonna be a hell if a job if the grid would increase though... :)
Yeah , it's intuition more importantly! In fact intuition is the birth of most algorithms and procedure in CS! :)
I keep getting 32!!!!!!!!! Someone please explain it to why the answer is 33(in easy words, I am only a 7 grader)
Log in to reply
(R = move right, U = move up) 2R-1U-2R-3U-1R-2U-2R, which gives 0+0+4+6+1+6+1+4+5+0+3+1+2+0 = 33 ( If you fill out the grid as per the algorithm, then you can determine a path that gives the maximum by working backwards from the upper right, going left or down to the box with the highest number of that pair. If they are both equal, you can take either path.
I get that the computer-generated answer is 33, but while trying to figure it out in head, I only got 32 as best route. Can somebody please point out the route that gives 33? No need for drawing, a 13 character long sequence of U (for up) and R (for right) is good enough for me ^_^
edit: Nevermind, found it. It's RRURRUUU RU URR. The italicized part can be inverted, so two solutions :D
I love that you made that programming interface just for this problem, it honestly made it 10x better than it would've otherwise been.
Log in to reply
It's not just for this problem, in the weekly problems for this week, they started popping up on other problems as well.
Your python code is correct but the comments explaining it above should have a “-“ instead of a “+”.
Log in to reply
I have specifically stated that the code is written assuming that we are starting from top left. But since the problem initially stated that we begin from bottom left, I gave the explanation accordingly.
im getting 31
Log in to reply
recheck you working. If you're still getting same answer it might be that your implementation of the algorithm is wrong.
Great solution but this doesn’t work for arbitrary grids. The problem has to do with the decision if both paths have the same value. One could construct a grid where the choice between ‘a tie’ matters.
Log in to reply
Yes in fact it does, this solution calculates the max possible value for every grid location (that is, the max value of every possible path to every single grid location).
to those that say they solved it "in my head", if you did it without writing anything down, that's very impressive. But if you wrote down the numbers(as most of us would have to) I'd call that "manually" and less impressive. In fact it's tedious, so that's where the programming really shines and makes it much more fun. Also, the solution is iterative, not recursive. Recursive would require calling a function recursively and (starting in the top-right) would probably just blow the stack. to print out the path you have to initialize a path variable e.g. on line 7 path = "" then replace the max function with separate paths of code e.g. replace lines 19 to 29 with
1 2 3 4 5 6 7 8 9 10 11 |
|
this assumes colmax and rowmax are unequal and there's only one maximum path, but it will always print a valid path.
Log in to reply
I have formatted your code correctly. You can click on "edit" to see how to do this.
Relevant wiki: Dynamic Programming
Solved with a spreadsheet (LibreOffice Calc).
Placed the numbers as shown on the A1..H7 grid.
In the cell J7 I placed the formula =MAX(I7,J8)+A7 and copied it to the J1..Q7 grid.
The result was in the cell Q1.
If you are interested in these problems have a look at the literature on Operational Research.
Matthew, isn't there an error? Moving from 22 to 6 is 28, not 29. I am only able to obtain 32 coins.
Relevant wiki: Dynamic Programming
I think it is a bit self explanatory, but anyway, let me explain:
The idea to get rid of the corners is not to define coordinates at -1, as this is ugly and quite a messy workaround. Instead, a function filters valid coordinates to retrieve from max_coins. Better yet would be to instead write a recursive function that would not even try values smaller than 0, but as Python is not tail-call optmized I don't think it would be very performant.
Then, to unravel the path, the concept is a lot similar from the one used in generating the max_coins list: just look from where there are the most coins and append it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
|
I believe the solution of either using pythons default dictionary value, or for more explicit and easily commendable code, setting the negative coordinates to 0, is less bulky and more efficient that calling an if statement for every lookup, especially if the grid size is large. The implementation of a default value also calls an if statement, though in C in a good implementation, but since we have prior knowledge of our own algorithm which python doesn't, we know that the only non positive values we'll call are -1 in some direction, then the most efficient solution is actually setting the negative edges to be 0. Get gud m8
The idea to get rid of initializing the cases for the first column and row can be accomplished using a feature of the implemented Python dictionary which allows you to return 0 for any non-existing coordinates like -1.
1 2 3 4 |
|
What is the path that you got?
Here is my solution:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
On closely examining the grid, you will notice that the grid has 6 only three times, out of which you can go through any two. You just have to now pick up the path that gives you the max. sum. The grid is so arranged that it supports this logic.
from brilliant import goldgrid
...
...
for column in range(1,width):
if max coins[(column-1,row)]> max coins[(column,row-1)]:
max coins[(column,row)] = max coins[(column-1,row)]+coins[(column,row)];
else:
max coins[(column,row)] = max coins[(column,row-1)]+coins[(column,row)];
..
print(max_coins[(width-1,height-1)])
Problem Loading...
Note Loading...
Set Loading...
Relevant wiki: Dynamic Programming
The Key to find the answer here is that , if you want to know the max number of coins to reach cell (i,j) then you can compute it recursively by knowing the no max coins to reach cell(i+1,j) and cell(i,j-1) ( assuming Adam starts from bottom left and goes to top right). Recursively:
Let F ( i , j ) be the function that gives max number of coins to reach cell (i,j) then, F ( i , j ) = m a x ( F ( i + 1 , j ) , F ( i , j − 1 ) ) + c o i n s ( i , j ) Giving the answer to be 3 3 Using DP can help avoid recalculate already calculated values and solve in O ( n ∗ m ) Time Complexity ( where m , n are rows and columns ) Hence Line 19 may be: (Note that the code has been written by taking rows and columns from topleft and so the condition has been modified accordingly!)