Algorithm to find max cost path of length N in matrix, from [0,0] to last row

后端 未结 4 931
走了就别回头了
走了就别回头了 2020-12-18 15:25

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

相关标签:
4条回答
  • 2020-12-18 15:56

    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]);
    
    0 讨论(0)
  • 2020-12-18 16:01

    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

    0 讨论(0)
  • 2020-12-18 16:02

    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.

    0 讨论(0)
  • 2020-12-18 16:18

    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 ;
    }
    
    0 讨论(0)
提交回复
热议问题