I am trying to solve problem similar to this problem at GeeksforGeeks, yet different:
Given a rectangular 2-d grid with some coin value present in each cell, the task is to start from the top-left and bottom-right corner going right or down, and from bottom-right to top-left going left or up, maximizing the combined amount of coin picked. Coin in each cell can be picked only once.
The solution in the link is to start both traversal simultaneously but that's not going to work here.
How should I solve this? The brute force way of doing this would be enumerating all paths and picking two paths that maximizes the sum of coins picked but that's not going to work for large input.

- 37,241
- 25
- 195
- 267

- 930
- 3
- 14
- 32
-
Use two memorization table `dp1[i][j][val]` and `dp2[i][j][val]` to avoid repeative calculation. – Kaidul Oct 19 '16 at 10:29
-
the two traversal independenlty? – Prashant Bhanarkar Oct 19 '16 at 10:30
-
Why you need to do simultaneously? The complexity for one traversal is `O(n * m * profit)`. For two separate traversal, its still `O(n * m * profit)` asymptotically. – Kaidul Oct 19 '16 at 10:34
-
It will fail for test case if we do traversal independently m1 = [ [0, 1, 0, 0, 0], [0, 1, 0, 1, 0], [1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0] ] – Prashant Bhanarkar Oct 19 '16 at 10:36
-
1Sorry. May be I didn't understand correctly. You must have to go in two separate route ? – Kaidul Oct 19 '16 at 10:38
-
Hint: Define f(i, j, k) to be the maximum score obtainable from traversing the first (topmost) i rows, given that wind up occupying columns j and k in this ith row. – j_random_hacker Oct 19 '16 at 12:49
-
1so to be clear you need to find 2 different paths? If a coin is removed by one path the other path can pass through the same square but will get no value for it? are the paths competing(they want to do the best for themselves) or are they working together (best total value)? – Jeff Oct 19 '16 at 16:34
-
yes we need to find 2 different paths.yes other path can pass but it will not get any value. they are working together best total value – Prashant Bhanarkar Oct 19 '16 at 18:07
-
@j_random_hacker I don't see how that recursion helps – Prashant Bhanarkar Oct 20 '16 at 15:44
-
The next step is to figure out how to calculate f(i, j, k) efficiently from already-computed values of f(). (You need to be familiar with dynamic programming to understand this; I suggest reading about the general topic first.) All I'll say now is that for this problem, this computation can be done in O(1) time, which implies an algorithm with overall time complexity O(n^3) for a square grid of side length n. – j_random_hacker Oct 20 '16 at 15:49
-
@j_random_hacker I am little bit familiar with dynamic programming, what I mean is let's say we computed the f(i,j,k) for the last row that is i is the last row.so using this information how the actual problem is solved? – Prashant Bhanarkar Oct 20 '16 at 16:36
-
If the two players are in columns j and k on row i, what is the complete set of column pairs that they could have occupied on row i-1? (I'm trying to give hints without giving the game away.) – j_random_hacker Oct 20 '16 at 16:54
-
1What part of solution given in geeksforgeeks you didnt understand @PrashantBhanarkar – Nikhil Pathania Oct 20 '16 at 17:45
-
@j_random_hacker any other hints? – Prashant Bhanarkar Oct 24 '16 at 14:25
-
Last hint: Given that we're now in rows j and k, there are at most 9 possible pairs of columns that we could have been in in the last row. – j_random_hacker Oct 24 '16 at 14:38
-
1Please describe the problem completely, instead of linking to an external source that the problem "is similar to". – m69's been on strike for years Oct 25 '16 at 02:09
-
In the problem presentation, describe _in how far and why_ an approach is doomed instead of just claiming so. – greybeard Oct 25 '16 at 09:59
-
1Does the direction of "the other traversal" matter? Try and understand j_random_hacker's hints - you may (of course!) [answer your own question](http://stackoverflow.com/help/badges/14/self-learner) on stackoverflow(/SE). – greybeard Oct 25 '16 at 10:03
-
(Consider awarding the bounty manually.) – greybeard Oct 31 '16 at 08:41
2 Answers
We can solve this problem by making three observations:
First, rather than starting at two different points, we can reverse the direction of the second person, so the problem become two people start at the top left corner and move toward bottom right corner simultaneously.
Second, if we make an assumption that, two persons will make their move at the same speed, the state of these two can be represented by only three parameters:
x1, x2 and y1
. As we can easily calculate the number of move the first person had made based on his current location (sumx1 + y1
, as he can only move right or down), so, we can also figure out the current location of second person (y2 = x1 + y1 - x2
). Keep in mind that, both need to make same number of step to reach the bottom right, so both will have same number of move in any given time.Lastly, We should notice that, a person cannot visit a location more than one, as the only directions each can take are right or down. Further more, in any state, the number of move each person made are equaled, so, if there exists location(s) visited by both persons, they will visit this location at the same time (and only when
x1 = x2
), thus, we can easily count the number of coins collected.
From these observations, it can be easily reduced to a similar problem to the problem in OP's link:
Starting from state (x1, x2, y1)
, as each person can only move right or down, we will have following next states:
(x1 + 1, x2 + 1, y1) : Both move to the right.
(x1 + 1, x2, y1) : First person move right, second move down
(x1, x2 + 1, y1 + 1) : First move down, second move right
(x1, x2, y1 + 1) : Both move down.
So, we have our dynamic programming formula:
dp[x1][x2][y1] = coin[x1][y1] + (x2 != x1 ? coin[x2][y2] : 0 ) + max(dp[x1 + 1][x2 + 1][y1], dp[x1 + 1][x2][y1], dp[x1][x2 + 1][y1 + 1], dp[x1][x2][y1 + 1])

- 11,204
- 2
- 24
- 43
-
1Whenever the two traversals go through the same square, moving down and right or moving right and down leads to two identical solutions, so in these cases you only need to look at three next states. – m69's been on strike for years Oct 27 '16 at 22:27
-
1
-
Its not working for the case m1 = [ [0, 2, 1], [1, 0, 0], [0, 2, 0] ] – Prashant Bhanarkar Nov 13 '16 at 07:11
-
@PrashantBhanarkar how is it not working? or your implementation not working? – Pham Trung Nov 13 '16 at 11:41
-
-
as per your formulation having only one y1 means both person will be at the same column but thats not true – Prashant Bhanarkar Nov 13 '16 at 16:11
-
@PrashantBhanarkar it returns 6 as expected. See [here](http://ideone.com/zhOUBl) – Pham Trung Nov 13 '16 at 16:26
-
my bad used (x1 + 1, x2, y1+1) when : First person move right, second move down but the correct as you mentioned is (x1 + 1, x2, y1) : First person move right, second move down – Prashant Bhanarkar Nov 13 '16 at 16:47
-
why (x2 != x1 ? coin[x2][y2] : 0 ) and not (x2 != x1 || y2 != y1? coin[x2][y2] : 0 )? Thank you – Bassam Mehanni Dec 09 '18 at 20:01
-
1@BassamMehanni if `x2 == x1`, so `y2 == y1` also. Two people making same number of step, and they can only go down or go to the right. – Pham Trung Dec 10 '18 at 03:46
-
@PhamTrung thank you so much, that makes sense. Awesome solution btw. – Bassam Mehanni Dec 11 '18 at 04:05
I'm not clear on the exact requirements for the 2 traversals you need but for any given traversal here is what I would suggest. Use Dijkstra's algorithm but build it such that instead of having the determining factor being the length/weight of a connection between 2 nodes make it the values of the grid square. It is also important to make sure it checks for the path with the max value instead of the min value.
Taking this approach should make it so that if there is more than one way to get to a square (which there will be most of the time) the algorithm will ignore all but the path that has accumulated the max value thereby reducing the number of paths that need to be checked.
ex:
Input :
int arr[R][C] = {{3, 6, 8},
{5, 2, 4},
{5, 1, 20},
{5, 1, 20, 10},
};
start: (0,0) 3
first step:
P1: (0,0) 3 , (1,1) 2 Total = 5
P2: (0,0) 3 , (1,0) 5 Total = 8
both are still in the running for the best path.
Step 2: both P1 and P2 can have their next step to (2,1) 1 in the brute force method you would have both paths continues through the rest of the graph but in this method we see P2 has a greater value than P1 so there is no need to continue with P1 and from that square onward just continue with P2.

- 407
- 4
- 17
-
well this approach you are greedily choosing will fail as there might be higher value that is along the path that we decided not to pick – Prashant Bhanarkar Oct 20 '16 at 15:43
-
how so? this is not a greedy algorithm, you check all paths until you find a point that has more than one way to get to it. when you find at least 2 possible paths that meet you evaluate all the paths net value to that point and find the best. Only then do you ignore any path that does not give the max value to that point. – Jeff Oct 21 '16 at 14:11
-
If P2 has a higher value on its way to point (2,1) then p1 does there is no way that p1 could get a higher value then p2 along the rest of the path. since p2 will be better than p1 for the rest of the possible paths (and therefore by the end of the trip) there is no need to continue with p1 and it is just unnecessary calculations. It will get the best path. – Jeff Oct 21 '16 at 14:12
-
If you are not familiar with Dijkstra's Algorithm you may want to watch this video (bearing in mind I'm suggesting an edit to it) and learn a bit more about it. https://www.youtube.com/watch?v=WN3Rb9wVYDY – Jeff Oct 21 '16 at 14:19
-
1Dijkstra's algorithm cannot be used to calculate max path. It is [NP-hard](https://en.m.wikipedia.org/wiki/Longest_path_problem) – Pham Trung Oct 26 '16 at 06:50
-
@PhamTrung that is true if the path can be any length but given the size of the matrix and the path can only be the length = to the height of the matrix doesn't that make it not NP-hard? If it's a 5 by 5 map then there can only be 5 steps in the path since step must travel down the map (or up the map if you start at the bottom). Dijkstra's algorithm could be used to determine if it is best to go down to the left cent or right. – Jeff Oct 26 '16 at 14:12
-
If you treat number of coin as weigh in the graph, it will not work, consider there are two paths from cell A to cell B, A -> 100 -> 20 -> B and A -> 10 -> 200 ->B, the second path will not be considered, even though it is better. – Pham Trung Oct 26 '16 at 15:39
-
(The last row of your example still looks odd. (And I needed several seconds to figure out the significance of `3`.)) – greybeard Oct 27 '16 at 05:29
-
(Didn't pay (due?) attention to your example.) You let `P2` start at `(0,0)`, the question reads `and from bottom-right to top-left`. Not sure about a single move changing both coordinates - the question regrettably is not as explicit about moves allowed as GeeksforGeeks. – greybeard Oct 27 '16 at 20:50
-
as I state in my first sentence I was providing an answer for one track, not both as it was not clear what the question wanted for the second track (requirements seemed different than the example). P1 and P2 are showing the different paths that are possible for one track starting at the top left. there are Pn possible tracks to get from the top left to the end destination, I am showing 2 and how picking the best would work. – Jeff Oct 29 '16 at 21:45