Reputation: 2048
Question: There is an m x n grid ( 0 <= m, n <= 500). Each cell in the grid contains k coins (k could be negative or 0 too). You start from 0, 0 and end at m-1, n-1, and you can move either 1 step down or 1 step right, collecting as many coins as you can. If k < 0, then that particular cell has a robber and you can't move into that cell. If you move into any of the 8 neighboring cells, you will be robbed of k coins. How many coins will you have when you reach m-1, n-1 ?
For example in the grid:
0,23,20,-32
13,14,44,-44
23,19,41,9
46,27,20,0
ans = 129 (by following the path: 0-13-23-46-27-20-0)
Time limit: 5 sec
I don't think this program can be solved using dynamic programming. And I haven't studied graph theory (in case it could be used to solve this problem). The straightforward recursive approach is the only thing I can think of, which is too inefficient under the given constraints.
So what would be a good approach to solve it? Don't just post code, tell me how to begin. If its related to graph theory, then indicating which theorem is involved would be very useful.
Upvotes: 3
Views: 4220
Reputation: 2972
Your problem could be described as a max-flow problem and thus be solved by the Ford-Fulkerson-Algorithm.
Transformation goes as follows:
There may be easier solutions, this is just the first thing that came to my mind.
Edit: As dasblinkenlight points out in the comments, this will not work, because a flow is actually the combination of multiple paths, which is of course not what we want here.
Upvotes: 0
Reputation: 727077
I don't think this program can be solved using dynamic programming.
Why not? This is a prime candidate for the dynamic programming approach.
The straightforward recursive approach is the only thing I can think of, which is too inefficient under the given constraints.
Can you build a recursive solution that solves, say, a 5x5 grid? Perfect! Start with that, and then memoize it by adding an MxN
array of best results for cells which you have already solved. Start that array with all large negative values, and then update it when you find a solution that is better. than what's there already. Once you 've finished with the cell, put the solution into the MxN
array: the next time you come there recursively, check the array for a number, and if a value is there, return it without continuing with the recursion.
The memoized solution itself is rather straightforward. The preprocessing step of the algorithm (subtracting negative numbers from neighboring cells) takes more code.
int solve(int r, int c) {
if(memo[r][c] != MIN) {
return memo[r][c];
}
int res = grid[r][c];
int a = 0, b = 0;
if (r+1 != R) {
a = solve(r+1, c);
}
if (c+1 != C) {
b = solve(r, c+1);
}
res = max(res+a, res+b);
return memo[r][c] = res;
}
Here is the solution on ideone, it returns 129
as expected.
Upvotes: 4
Reputation: 839224
Your problem is called the longest path problem for a weighted directed acyclic graph.
The most number of coins you can have when you reach (x,y) is given by:
coins(x,y) = max(coins(x-1,y), coins(x,y-1)) + change
This is a recurrence relationship. It can be solved either by using recursion and memoization for performance, or by using an iterative algorithm.
The iterative algorithm is to work through the grid one diagonal at a time. Start at 0,0. Then calculate 0,1 and 1,0. Then 0,2 and 1,1 and 2,0. etc...
Step 1:
0, ?, ?, ?
?, ?, ?, ?
?, ?, ?, ?
?, ?, ?, ?
Step 2:
0, 23, ?, ?
13, ?, ?, ?
?, ?, ?, ?
?, ?, ?, ?
Step 3:
0, 23,-33, ?
13, 37, ?, ? // 37 because of max(23,13) + 14
36, ?, ?, ?
?, ?, ?, ?
etc...
When you complete this process, the answer is the number in the bottom-right corner.
Upvotes: 4