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++
#include <bits/stdc++.h>
using namespace std;
const int size = 1000;
int maxCost( int a[][size], int m, int n)
{
if (n < 0 || m < 0)
return -1e9;
else if (m == 0 && n == 0)
return 0;
else {
int num = m + n;
if ((num & (num - 1)) == 0)
return a[m][n] + maxCost(a, m - 1, n - 1);
else
return a[m][n] + max(maxCost(a, m - 1, n),
maxCost(a, m, n - 1));
}
}
int answer( int a[][size], int n)
{
return maxCost(a, n - 1, n - 1);
}
int main()
{
int a[][size] = { { 1, 2, 3, 1 },
{ 4, 5, 6, 1 },
{ 7, 8, 9, 1 },
{ 1, 1, 1, 1 } };
int n = 4;
cout << answer(a, n);
return 0;
}
|
Java
class GFG {
static int size = 1000 ;
public static int maxCost( int [][] a, int m, int n)
{
if (n < 0 || m < 0 ) {
return - 1 ;
}
else if (m == 0 && n == 0 ) {
return 0 ;
}
else {
int num = m + n;
if ((num & (num - 1 )) == 0 ) {
return a[m][n] + maxCost(a, m - 1 , n - 1 );
}
else {
return a[m][n] + Math.max(maxCost(a, m - 1 , n), maxCost(a, m, n - 1 ));
}
}
}
public static int answer( int [][] a, int n)
{
return maxCost(a, n - 1 , n - 1 );
}
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));
}
}
|
Python3
size = 1000
def maxCost(a: list , m: int , n: int ) - > int :
if n < 0 or m < 0 :
return int ( - 1e9 )
elif m = = 0 and n = = 0 :
return 0
else :
num = m + n
if (num & (num - 1 )) = = 0 :
return a[m][n] + maxCost(a, m - 1 , n - 1 )
else :
return a[m][n] + max (maxCost(a, m - 1 , n), maxCost(a, m, n - 1 ))
def answer(a: list , n: int ) - > int :
return maxCost(a, n - 1 , n - 1 )
if __name__ = = "__main__" :
a = [[ 1 , 2 , 3 , 1 ],
[ 4 , 5 , 6 , 1 ],
[ 7 , 8 , 9 , 1 ],
[ 1 , 1 , 1 , 1 ]]
n = 4
print (answer(a, n))
|
C#
using System;
class GFG {
static int size = 1000;
public static int maxCost( int [, ] a, int m, int n)
{
if (n < 0 || m < 0)
return -1;
else if (m == 0 && n == 0)
return 0;
else {
int num = m + n;
if ((num & (num - 1)) == 0)
return a[m, n] + maxCost(a, m - 1, n - 1);
else
return a[m, n] + Math.Max(maxCost(a, m - 1, n), maxCost(a, m, n - 1));
}
}
public static int answer( int [, ] a, int n)
{
return maxCost(a, n - 1, n - 1);
}
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;
Console.Write(answer(a, n));
}
}
|
Javascript
<script>
let size = 1000;
function maxCost(a,m,n)
{
if (n < 0 || m < 0) {
return -1;
}
else if (m == 0 && n == 0) {
return 0;
}
else {
let num = m + n;
if ((num & (num - 1)) == 0) {
return a[m][n] + maxCost(a, m - 1, n - 1);
}
else {
return a[m][n] + Math.max(maxCost(a, m - 1, n), maxCost(a, m, n - 1));
}
}
}
function answer(a,n)
{
return maxCost(a, n - 1, n - 1);
}
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));
</script>
|
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++
#include <bits/stdc++.h>
using namespace std;
const int size = 1000;
int maxCost( int a[][size], int m, int n, int dp[][size])
{
if (n < 0 || m < 0)
return -1e9;
else if (m == 0 && n == 0)
return 0;
else if (dp[m][n] != -1)
return dp[m][n];
else {
int num = m + n;
if ((num & (num - 1)) == 0)
return dp[m][n] = a[m][n] + maxCost(a, m - 1, n - 1, dp);
else
return dp[m][n] = (a[m][n] + max(maxCost(a, m - 1, n, dp),
maxCost(a, m, n - 1, dp)));
}
}
int answer( int a[][size], int n)
{
int dp[size][size];
memset (dp, -1, sizeof dp);
return maxCost(a, n - 1, n - 1, dp);
}
int main()
{
int a[][size] = { { 1, 2, 3, 1 },
{ 4, 5, 6, 1 },
{ 7, 8, 9, 1 },
{ 1, 1, 1, 1 } };
int n = 4;
cout << answer(a, n);
return 0;
}
|
Java
class GFG {
static int size = 1000 ;
static int maxCost( int a[][], int m, int n, int dp[][])
{
if (n < 0 || m < 0 )
return ( int )-1e9;
else if (m == 0 && n == 0 )
return 0 ;
else if (dp[m][n] != - 1 )
return dp[m][n];
else {
int num = m + n;
if ((num & (num - 1 )) == 0 )
return dp[m][n] = a[m][n] + maxCost(a, m - 1 , n - 1 , dp);
else
return dp[m][n] = (a[m][n] + Math.max(maxCost(a, m - 1 , n, dp),
maxCost(a, m, n - 1 , dp)));
}
}
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 ;
}
}
return maxCost(a, n - 1 , n - 1 , dp);
}
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 ;
System.out.println(answer(a, n));
}
}
|
Python3
size = 1000 ;
def maxCost(a, m, n, dp):
if (n < 0 or m < 0 ):
return int ( - 1e9 );
elif (m = = 0 and n = = 0 ):
return 0 ;
elif (dp[m][n] ! = - 1 ):
return dp[m][n];
else :
num = m + n;
if ((num & (num - 1 )) = = 0 ):
dp[m][n] = a[m][n] + maxCost(a, m - 1 , n - 1 , dp);
return dp[m][n];
else :
dp[m][n] = (a[m][n] + max (maxCost(a, m - 1 , n, dp), maxCost(a, m, n - 1 , dp)));
return dp[m][n];
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 ;
return maxCost(a, n - 1 , n - 1 , dp);
if __name__ = = '__main__' :
a = [[ 1 , 2 , 3 , 1 ],[ 4 , 5 , 6 , 1 ],[ 7 , 8 , 9 , 1 ],[ 1 , 1 , 1 , 1 ]];
n = 4 ;
print (answer(a, n));
|
C#
using System;
class GFG
{
static int size = 1000;
static int maxCost( int [,]a, int m, int n, int [,]dp)
{
if (n < 0 || m < 0)
return ( int )-1e9;
else if (m == 0 && n == 0)
return 0;
else if (dp[m, n] != -1)
return dp[m,n];
else {
int num = m + n;
if ((num & (num - 1)) == 0)
return dp[m, n] = a[m, n] + maxCost(a, m - 1, n - 1, dp);
else
return dp[m,n] = (a[m,n] + Math.Max(maxCost(a, m - 1, n, dp),
maxCost(a, m, n - 1, dp)));
}
}
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;
}
}
return maxCost(a, n - 1, n - 1, dp);
}
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;
Console.WriteLine(answer(a, n));
}
}
|
Javascript
<script>
let size = 1000;
function maxCost(a,m,n,dp)
{
if (n < 0 || m < 0)
return -1e9;
else if (m == 0 && n == 0)
return 0;
else if (dp[m][n] != -1)
return dp[m][n];
else {
let num = m + n;
if ((num & (num - 1)) == 0)
return dp[m][n] = a[m][n] + maxCost(a, m - 1, n - 1, dp);
else
return dp[m][n] = (a[m][n] + Math.max(maxCost(a, m - 1, n, dp),
maxCost(a, m, n - 1, dp)));
}
}
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;
}
}
return maxCost(a, n - 1, n - 1, dp);
}
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));
</script>
|
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.
Last Updated :
29 Aug, 2022
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...