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++
// 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; } |
Java
// 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 */ |
Python3
# Python program for # SP - Wolfish size = 1000 # Function to find the maxCost of path from # (n-1, n-1) to (0, 0) | recursive approach def maxCost(a: list , m: int , n: int ) - > int : # base condition if n < 0 or m < 0 : return int ( - 1e9 ) # reaches the point elif m = = 0 and n = = 0 : return 0 else : # i + j 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 def answer(a: list , n: int ) - > int : # calling dp function to get the answer return maxCost(a, n - 1 , n - 1 ) # Driver Code if __name__ = = "__main__" : a = [[ 1 , 2 , 3 , 1 ], [ 4 , 5 , 6 , 1 ], [ 7 , 8 , 9 , 1 ], [ 1 , 1 , 1 , 1 ]] n = 4 # Function calling to get the answer print (answer(a, n)) # This code is contributed by # sanjeev2552 |
C#
// 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_ } |
Javascript
<script> // Javascript program for SP - Wolfish let size = 1000; // Function to find the maxCost of path from // (n-1, n-1) to (0, 0) | recursive approach function maxCost(a,m,n) { // base condition if (n < 0 || m < 0) { return -1; } // reaches the point else if (m == 0 && n == 0) { return 0; } else { // i + j let 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 function answer(a,n) { // calling dp function to get the answer return maxCost(a, n - 1, n - 1); } // Driver Code let a=[[ 1, 2, 3, 1 ],[ 4, 5, 6, 1 ], [ 7, 8, 9, 1 ], [ 1, 1, 1, 1 ]]; let n = 4; document.write(answer(a, n)); // This code is contributed by rag2127 </script> |
16
Time Complexity: O(2N)
Approach using Memoization
In the above recursion, many sub-problems are being repeatedly called. To reduce the number of repetitive 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++
// 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; } |
Java
// 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 |
Python3
# Python program for SP - Wolfish size = 1000 ; # Function to find the maxCost of path from # (n-1, n-1) to (0, 0) def maxCost(a, m, n, dp): # base condition if (n < 0 or m < 0 ): return int ( - 1e9 ); # reaches the point elif (m = = 0 and n = = 0 ): return 0 ; # if the state has been visited previously elif (dp[m][n] ! = - 1 ): return dp[m][n]; else : # i + j num = m + n; # check if it is a power of 2, # then only move diagonally if ((num & (num - 1 )) = = 0 ): dp[m][n] = a[m][n] + maxCost(a, m - 1 , n - 1 , dp); return dp[m][n]; # if not a power of 2 # then move side-wise else : dp[m][n] = (a[m][n] + max (maxCost(a, m - 1 , n, dp), maxCost(a, m, n - 1 , dp))); return dp[m][n]; # Function to return the maximum cost def answer(a, n): dp = [[ 0 for i in range (size)] for j in range (size)] ; for i in range (size): for j in range (size): dp[i][j] = - 1 ; # calling dp function to get the answer return maxCost(a, n - 1 , n - 1 , dp); # Driver Code if __name__ = = '__main__' : a = [[ 1 , 2 , 3 , 1 ],[ 4 , 5 , 6 , 1 ],[ 7 , 8 , 9 , 1 ],[ 1 , 1 , 1 , 1 ]]; n = 4 ; # Function calling to get the answer print (answer(a, n)); # This code contributed by Rajput-Ji |
C#
// 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 |
Javascript
<script> // Javascript program for SP - Wolfish let size = 1000; // Function to find the maxCost of path from // (n-1, n-1) to (0, 0) function maxCost(a,m,n,dp) { // 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 let 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 function answer(a,n) { let dp = new Array(size); for (let i = 0; i < size; i++) { dp[i]= new Array(size); for (let 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 let a=[[ 1, 2, 3, 1 ], [ 4, 5, 6, 1 ], [ 7, 8, 9, 1 ], [ 1, 1, 1, 1 ]]; let n = 4; // Function calling to get the answer document.write(answer(a, n)); // This code is contributed by avanitrachhadiya2155 </script> |
16
Complexity Analysis:
- 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.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!