I have a n*n
matrix, where each element represents an integer. Starting in [0,0]
I have to find the path of exactly m
elements down to
This is actually a DAG, and therefore the dynamic programming solution to the longest path problem works.
Why a DAG, you say? There is an obvious cycle going from two vertices that are horizontally adjacent. If you use the "obvious" graph, of course.
The less obvious approach is to rework this as a graph of (vertex, direction), in which direction is the last direction you took from down/left/right. A vertex that has direction down can go either down, left, or right, whereas a vertex with direction right can only go down/right, and a vertex with direction left can only go left/down. This graph is clearly acyclic, and it comprises all possible paths in the original matrix.
Therefore, ignoring the limit m
, a possible recursion for the longest path to (a, b, direction) is
pdl[i][j] = max(pdl[i][j-1], pd[i-1][j])+arr[i][j]; pdr[i][j] = max(pdr[i][j+1], pd[i-1][j])+arr[i][j]; pd[i][j] = max(pdl[i][j], pdr[i][j]);
pd
is the array for the "down" vertices, pdr
for right and pdl
is for left. As an implementation detail, note that I keep the max of the left and corresponding down vertex in pdl
, but this doesn't really matter as any vertex with direction "down" can go left and down just as a "left" vertex would. Same for pdr
.
The limit means you'll have to add another dimension to that DP solution, that is, you have to keep pd[i][j][moves]
, that keeps the highest sum possible until vertex (i, j) using exactly moves
movements, obtaining the recursion
pdl[i][j][moves] = max(pdl[i][j-1][moves-1], pd[i-1][j][moves-1])+arr[i][j]; pdr[i][j][moves] = max(pdr[i][j+1][moves-1], pd[i-1][j][moves-1])+arr[i][j]; pd[i][j][moves] = max(pdl[i][j][moves-1], pdr[i][j][moves-1]);
You can solve this problem with dynamic programming. Let value(i, j)
the value from position (i, j)
of your matrix (i-th line, j-th column).
if i < 0 then f(i, j) = 0
if i == 0 then f(i, j) = value(i, j)
if i > 0 then f(i, j) = max(f(i-1, j), f(i, j-1)) + value(i, j)
That recurrence assume that you use a position from your matrix when you step down. So, you answer is max(f(m, 0), f(m-1, 1), f(m - 2, 2), ..., f(1, m))
.
For example:
Give the follow matrix for n = 4
:
1 1 1 1
1 2 1 1
2 1 1 1
1 2 1 1
If m = 2
then you cant go after second line. And you answer is f(2, 2) = 4
.
If m = 4
then you cant go after third line. And you answer is f(3, 2) = 5
.
(Im learning english so If you didnt understand something let me know and I will try to improve my explanation).
Edit :: allow down/left/right moves
You can implement follow recurrence:
if i == n, j == n, p == m, j == 0 then f(i, j, p, d) = 0
if d == DOWN then f(i, j, p, d) = max(f(i+1, j, p+1, DOWN), f(i, j-1, p+1, RIGHT), f(i, j+1, p+1,LEFT)) + value(i, j)
if d == LEFT then f(i, j, p, d) = max(f(i+1, j, p+1, DOWN), f(i, j+1, p+1, LEFT )) + value(i, j)
if d == RIGHT then f(i, j, p, d) = max(f(i+1, j, p+1, DOWN), f(i, j-1, p+1, RIGHT)) + value(i, j)
This solution is O(n^4)
. Im trying to improve it.
You can test it at http://ideone.com/tbH1j
This problem is very known. The most efficient way of doing this is dynamic programming.
Let dp[i][j]
is the maximum sum when coming to i,j from 0,0.
Then, dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + matrix[i][j]
;
After doing this, check every value of position where you are able to go and get the maximum value.
This Question can be solved using recursion and backtracking. Keep the count of steps covered till now and the cost of path till now.
Here is my implementation https://ideone.com/N6T55p
void fun_me(int arr[4][4], int m, int n,int i,int j,int steps,int cost)
{
//cout<<steps<<endl;
if(i>=n || j>=n)
return;
visited[i][j]=1;
if(i==n-1 && steps==m-1)
{
if(maxer<arr[i][j]+cost)
maxer=arr[i][j]+cost;
//cout<<arr[i][j]+cost<<endl;
}
if(isvalid(i+1,j,n) && !visited[i+1][j])
fun_me(arr,m,n,i+1,j,steps+1,cost+arr[i][j]);
if(isvalid(i,j+1,n) && !visited[i][j+1])
fun_me(arr,m,n,i,j+1,steps+1,cost+arr[i][j]);
if(isvalid(i,j-1,n) && !visited[i][j-1])
fun_me(arr,m,n,i,j-1,steps+1,cost+arr[i][j]);
visited[i][j]=0;
return ;
}