Sudo Placement[1.5] | Wolfish

Given a N x N matrix where value at cell (i, j) is the cost of moving from a cell (i, j) to cell (i – 1, j – 1), (i – 1, j) or (i, j – 1). Your task is to find the maximum cost path from (N – 1, N – 1) cell to (0, 0) cell in the N x N matrix (0 – based indexing). However, you have some restrictions on the movement from one cell to the other cell. If you are at (i, j) cell and (i + j) is a power of 2, you can only move to (i – 1, j – 1) cell. If (i + j) is not a power of 2 then you can move to (i – 1, j) or (i, j – 1)

Examples:

Input :[1 2 3 1
        4 5 6 1
        7 8 9 1
        1 1 1 1]
Output: 16 
The maximum cost path is: 
(3, 3) -> (3, 2) -> (2, 2) -> (1, 1) -> (0, 0).
Cost pathwise is: 
1 + 1 + 9 + 5 = 16.

Input: [1 2 
        3 4]
Output: 4 

Optimal Substructure:
The problem is a variation of Min-Cost problem. The path to reach (0, 0) from (n-1, n-1) must be through the three cells (i, j-1) or (i-1, j) or (i-1, j-1). A top-down recursive function will be called, for every value of m and n, check if (m+n) is a power of 2 or not. If it is a power of 2, then move to cell(m-1, n-1) and add the value at a[m][n]. Hence the cost will be:

cost = a[m][n] + maxCost(a, m – 1, n – 1)

If it is not a power of 2, then we can move to two of cells (m-1, n) and (m, n-1). So the cost will be:

cost = a[m][n] + max(maxCost(a, m – 1, n), maxCost(a, m, n – 1))

Below is the recursive implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program for
// SP - Wolfish
#include <bits/stdc++.h>
using namespace std;
  
const int size = 1000;
  
// Function to find the maxCost of path from
// (n-1, n-1) to (0, 0) | recursive approach
int maxCost(int a[][size], int m, int n)
{
    // base condition
    if (n < 0 || m < 0)
        return -1e9;
  
    // reaches the point
    else if (m == 0 && n == 0)
        return 0;
  
    else {
  
        // i + j
        int num = m + n;
  
        // check if it is a power of 2,
        // then only move diagonally
        if ((num & (num - 1)) == 0)
            return a[m][n] + maxCost(a, m - 1, n - 1);
  
        // if not a power of 2
        // then move side-wise
        else
            return a[m][n] + max(maxCost(a, m - 1, n),
                                 maxCost(a, m, n - 1));
    }
}
  
// Function to return the maximum cost
int answer(int a[][size], int n)
{
    // calling dp function to get the answer
    return maxCost(a, n - 1, n - 1);
}
  
// Driver Code
int main()
{
    int a[][size] = { { 1, 2, 3, 1 },
                      { 4, 5, 6, 1 },
                      { 7, 8, 9, 1 },
                      { 1, 1, 1, 1 } };
    int n = 4;
  
    // Function calling to get the answer
    cout << answer(a, n);
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program for SP - Wolfish
class GFG {
  
    static int size = 1000;
  
    // Function to find the maxCost of path from
    // (n-1, n-1) to (0, 0) | recursive approach
    public static int maxCost(int[][] a, int m, int n)
    {
        // base condition
        if (n < 0 || m < 0) {
            return -1;
        }
  
        // reaches the point
        else if (m == 0 && n == 0) {
            return 0;
        }
        else {
  
            // i + j
            int num = m + n;
  
            // check if it is a power of 2,
            // then only move diagonally
            if ((num & (num - 1)) == 0) {
                return a[m][n] + maxCost(a, m - 1, n - 1);
            }
  
            // if not a power of 2
            // then move side-wise
            else {
                return a[m][n] + Math.max(maxCost(a, m - 1, n), maxCost(a, m, n - 1));
            }
        }
    }
  
    // Function to return the maximum cost
    public static int answer(int[][] a, int n)
    {
        // calling dp function to get the answer
        return maxCost(a, n - 1, n - 1);
    }
  
    // Driver Code
    public static void main(String[] args)
    {
        int[][] a = new int[][] { { 1, 2, 3, 1 },
                                  { 4, 5, 6, 1 },
                                  { 7, 8, 9, 1 },
                                  { 1, 1, 1, 1 } };
        int n = 4;
  
        System.out.println(answer(a, n));
    }
}
  
/* This code contributed by PrinciRaj1992 */

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program for
// SP - Wolfish
using System;
  
class GFG {
    static int size = 1000;
  
    // Function to find the maxCost of path from
    // (n-1, n-1) to (0, 0) | recursive approach
    public static int maxCost(int[, ] a, int m, int n)
    {
        // base condition
        if (n < 0 || m < 0)
            return -1;
  
        // reaches the point
        else if (m == 0 && n == 0)
            return 0;
  
        else {
  
            // i + j
            int num = m + n;
  
            // check if it is a power of 2,
            // then only move diagonally
            if ((num & (num - 1)) == 0)
                return a[m, n] + maxCost(a, m - 1, n - 1);
  
            // if not a power of 2
            // then move side-wise
            else
                return a[m, n] + Math.Max(maxCost(a, m - 1, n), maxCost(a, m, n - 1));
        }
    }
  
    // Function to return the maximum cost
    public static int answer(int[, ] a, int n)
    {
        // calling dp function to get the answer
        return maxCost(a, n - 1, n - 1);
    }
  
    // Driver Code
    static void Main()
    {
        int[, ] a = new int[, ] { { 1, 2, 3, 1 },
                                  { 4, 5, 6, 1 },
                                  { 7, 8, 9, 1 },
                                  { 1, 1, 1, 1 } };
        int n = 4;
  
        // Function calling to get the answer
        Console.Write(answer(a, n));
    }
    // This code is contributed by DrRoot_
}

chevron_right


Output:

16

Time Complexity: O(2N)

Approach using Memoization

In the above recursion, many sub-problems are being repeatedly called. To reduce the number of repetative calls, memoization has been used. The common point of observation is that only two parameters value are changing at every function call. So if we memoize the returned value in a dp[][] array, the number of calls will be reduced to N^2. Hence store the computed value of every maxCost(m, n) in dp[m][n]. If the maxCost(m, n) is called more than once, then the extra calls of the function will be reduced by returning the value stored at dp[m][n].

Below is the efficient implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program for SP - Wolfish
#include <bits/stdc++.h>
using namespace std;
  
const int size = 1000;
  
// Function to find the maxCost of path from
// (n-1, n-1) to (0, 0)
int maxCost(int a[][size], int m, int n, int dp[][size])
{
    // base condition
    if (n < 0 || m < 0)
        return -1e9;
  
    // reaches the point
    else if (m == 0 && n == 0)
        return 0;
  
    // if the state has been visited previously
    else if (dp[m][n] != -1)
        return dp[m][n];
    else {
  
        // i + j
        int num = m + n;
  
        // check if it is a power of 2,
        // then only move diagonally
        if ((num & (num - 1)) == 0)
            return dp[m][n] = a[m][n] + maxCost(a, m - 1, n - 1, dp);
  
        // if not a power of 2
        // then move side-wise
        else
            return dp[m][n] = (a[m][n] + max(maxCost(a, m - 1, n, dp),
                                             maxCost(a, m, n - 1, dp)));
    }
}
  
// Function to return the maximum cost
int answer(int a[][size], int n)
{
    int dp[size][size];
    memset(dp, -1, sizeof dp);
  
    // calling dp function to get the answer
    return maxCost(a, n - 1, n - 1, dp);
}
  
// Driver Code
int main()
{
    int a[][size] = { { 1, 2, 3, 1 },
                      { 4, 5, 6, 1 },
                      { 7, 8, 9, 1 },
                      { 1, 1, 1, 1 } };
    int n = 4;
  
    // Function calling to get the answer
    cout << answer(a, n);
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program for SP - Wolfish
  
class GFG {
  
    static int size = 1000;
  
    // Function to find the maxCost of path from
    // (n-1, n-1) to (0, 0)
    static int maxCost(int a[][], int m, int n, int dp[][])
    {
        // base condition
        if (n < 0 || m < 0)
            return (int)-1e9;
  
        // reaches the point
        else if (m == 0 && n == 0)
            return 0;
  
        // if the state has been visited previously
        else if (dp[m][n] != -1)
            return dp[m][n];
        else {
  
            // i + j
            int num = m + n;
  
            // check if it is a power of 2,
            // then only move diagonally
            if ((num & (num - 1)) == 0)
                return dp[m][n] = a[m][n] + maxCost(a, m - 1, n - 1, dp);
  
            // if not a power of 2
            // then move side-wise
            else
                return dp[m][n] = (a[m][n] + Math.max(maxCost(a, m - 1, n, dp),
                                                      maxCost(a, m, n - 1, dp)));
        }
    }
  
    // Function to return the maximum cost
    static int answer(int a[][], int n)
    {
        int dp[][] = new int[size][size];
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                dp[i][j] = -1;
            }
        }
  
        // calling dp function to get the answer
        return maxCost(a, n - 1, n - 1, dp);
    }
  
    // Driver Code
    public static void main(String[] args)
    {
        int a[][] = { { 1, 2, 3, 1 },
                      { 4, 5, 6, 1 },
                      { 7, 8, 9, 1 },
                      { 1, 1, 1, 1 } };
        int n = 4;
  
        // Function calling to get the answer
        System.out.println(answer(a, n));
    }
}
// This code has been contributed by 29AjayKumar

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program for SP - Wolfish
using System; 
      
class GFG 
{
  
    static int size = 1000;
  
    // Function to find the maxCost of path from
    // (n-1, n-1) to (0, 0)
    static int maxCost(int [,]a, int m, int n, int [,]dp)
    {
        // base condition
        if (n < 0 || m < 0)
            return (int)-1e9;
  
        // reaches the point
        else if (m == 0 && n == 0)
            return 0;
  
        // if the state has been visited previously
        else if (dp[m, n] != -1)
            return dp[m,n];
        else {
  
            // i + j
            int num = m + n;
  
            // check if it is a power of 2,
            // then only move diagonally
            if ((num & (num - 1)) == 0)
                return dp[m, n] = a[m, n] + maxCost(a, m - 1, n - 1, dp);
  
            // if not a power of 2
            // then move side-wise
            else
                return dp[m,n] = (a[m,n] + Math.Max(maxCost(a, m - 1, n, dp),
                                                    maxCost(a, m, n - 1, dp)));
        }
    }
  
    // Function to return the maximum cost
    static int answer(int [,]a, int n)
    {
        int [,]dp = new int[size,size];
        for (int i = 0; i < size; i++)
        {
            for (int j = 0; j < size; j++) 
            {
                dp[i, j] = -1;
            }
        }
  
        // calling dp function to get the answer
        return maxCost(a, n - 1, n - 1, dp);
    }
  
    // Driver Code
    public static void Main(String[] args)
    {
        int [,]a = { { 1, 2, 3, 1 },
                    { 4, 5, 6, 1 },
                    { 7, 8, 9, 1 },
                    { 1, 1, 1, 1 } };
        int n = 4;
  
        // Function calling to get the answer
        Console.WriteLine(answer(a, n));
    }
}
  
// This code contributed by Rajput-Ji

chevron_right


Output:

16

Time Complexity: O(N2)
Auxiliary Space: O(N2)

Note: To implement a bottom-up approach, we need to check if ((m+1) + (n+1)) is a power of 2 or not instead of (m+n) as the moves are in top-down order.



My Personal Notes arrow_drop_up

Striver(underscore)79 at Codechef and codeforces D

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.