Given an array arr[] of size N describing N moves. A player standing at origin (0, 0). In the first move, the player can move either right or left by distance arr[1]. In the second move, the player can move up or down by distance arr[2], In the third move player can move left or right by distance arr[3], and so on till arr[N]. That is on odd moves player moves along the X coordinate and on even moves, the player moves along the Y coordinate. The task for this problem is to check whether coordinate (X, Y) is reachable from (0, 0) if the player performs these moves optimally. If this is possible print “Yes” else print “No”.
Examples :
Input: A[] = {2, 1, 3}, X = -1, Y = 1
Output: Yes
Explanation:Following is one of the possible ways to reach at (-1, 1)
- In first move player moves to (2, 0) by moving along positive direction of X co-ordinate by distance 2
- In second move player moves to (2, 1) by moving along positive direction of Y co-ordinate by distance 1
- In Third move player moves to (-1, 1) by moving along negative direction of X co-ordinate by distance 3
Input: A[] = {1, 2, 3, 4}, X = 5, Y = 5
Output: No
Naive approach: The basic way to solve the problem is as follows:
Visiting all possible co-ordinates by recursive brute force in exponential time.
Complexity Analysis:
Time Complexity: O(2N)
Auxiliary Space: O(1)
Efficient Approach: The above approach can be optimized based on the following idea
Important observation is that this problem can independently solved for both coordinates X and Y.
Lets reduce this problem to 1 dimension. Players starts from 0.
- Problem 1: Player has to reach on coordinate X by following moves {A[1], A[3], A[5], …….} on each move player can move back and forth by distance A[i].
- Problem 2: Player has to reach on coordinate Y by following moves {A[2], A[4], A[6], ……..} on each move player can move back and forth by distance A[i].
Dynamic programming can be used to solve this problem for each independent coordinate.
- dp[i][j] is either True or False, represents whether coordinate j is reachable or not in first i moves.
- recurrence relation : dp[i][j] = max(dp[i + 1][j + A[i]], dp[i + 1][j – A[i]])
it can be observed that there are N * AMax states but the recursive function is called exponential times. That means that some states are called repeatedly. So the idea is to store the value of states. This can be done using recursive structure intact and just store the value in a HashMap and whenever the function is called, return the value store without computing
- if both X and Y coordinates are reachable independently then coordinate (X, Y) is also reachable for player.
Follow the steps below to solve the problem:
- Creating two different array A1[] and A2[] for two independent problems and calling recursive function recur() for both.
- Create a recursive function that takes two parameters i representing i’th move and j represents current coordinate.
- Call recursive function for both moving right or up and left or down.
- Check the base case if at the end of Nth move we are on T which is target co-ordinate then return 1 else return 0.
- Create an 2d array of dp[501][10001] with initially filled with -1.
- If the answer for a particular state is computed then save it in dp[i][j].
- If the answer for a particular state is already computed then just return dp[i][j].
- Create two variables isPossibleX and isPossibleY for storing answer of two independent problems.
- If isPossibleX and isPossibleY both are 1 then print “Yes” else print “No”.
Below is the implementation of the above approach.
C++
// C++ code to implement the approach #include <bits/stdc++.h> using namespace std; // dp table initialized with - 1 int dp[501][20001]; // recursive function to tell whether // given coordinate (X, Y) is reachable // or not from origin int recur( int i, int j, int T, vector< int >& A) { // base case if (i == A.size()) { // if T is possible return 1 if (j == T) return 1; else return 0; } // if answer for current state is already // calculated then just return dp[i][j] // + 10000 is offset value to also include // negative numbers in states if (dp[i][j + 10000] != -1) return dp[i][j + 10000]; int ans = 0; // calling recursive function to move Right // in case of X coordinate or UP in case of // Y coordinate by distance A[i] ans = max(ans, recur(i + 1, j + A[i], T, A)); // calling recursive function to move Left // in case of X coordinate or Down in case of // Y coordinate by distance A[i] ans = max(ans, recur(i + 1, j - A[i], T, A)); // save and return dp value return dp[i][j + 10000] = ans; } // Function to check whether given // Coordinates (X, Y) is reachable // from origin void isReachable( int A[], int N, int X, int Y) { // creating two different arrays A1 // for solving X coordinate and A2 // for solving Y coordinate vector< int > A1, A2; // filling both the A1 and A2 for ( int i = 0; i < N; i++) { if (i % 2 == 0) A1.push_back(A[i]); else A2.push_back(A[i]); } // filling dp table with -1 memset (dp, -1, sizeof (dp)); // to check whether Reaching X // coordinate is possible by moves // {A[1], A[3], A[5], A[7], .....} int isPossibleX = recur(0, 0, X, A1); // filling dp table with -1 memset (dp, -1, sizeof (dp)); // to check whether Reaching Y // coordinate is possible by moves // {A[2], A[4], A[6], ........} int isPossibleY = recur(0, 0, Y, A2); // if reaching X and Y coordinates Both // are possible then only reaching on (X, Y) // is possible by player if (isPossibleX and isPossibleY) cout << "Yes" << endl; else cout << "No" << endl; } // Driver Code int main() { // Input 1 int A[] = { 2, 1, 3 }; int N = sizeof (A) / sizeof (A[0]); int X = -1, Y = 1; // Function Call isReachable(A, N, X, Y); // Input 2 int A1[] = { 1, 2, 3, 4 }; int N1 = sizeof (A1) / sizeof (A1[0]); int X1 = 5, Y1 = 5; // Function Call isReachable(A1, N1, X1, Y1); return 0; } |
Java
// Java code to implement the approach import java.io.*; import java.util.*; class GFG { // dp table initialized with - 1 static int [][] dp = new int [ 501 ][ 20001 ]; // recursive function to tell whether // given coordinate (X, Y) is reachable // or not from origin public static int recur( int i, int j, int T, Vector<Integer> A) { // base case if (i == A.size()) { // if T is possible return 1 if (j == T) return 1 ; else return 0 ; } // if answer for current state is already // calculated then just return dp[i][j] // + 10000 is offset value to also include // negative numbers in states if (dp[i][j + 10000 ] != - 1 ) return dp[i][j + 10000 ]; int ans = 0 ; // calling recursive function to move Right // in case of X coordinate or UP in case of // Y coordinate by distance A[i] ans = Math.max(ans, recur(i + 1 , j + A.get(i), T, A)); // calling recursive function to move Left // in case of X coordinate or Down in case of // Y coordinate by distance A[i] ans = Math.max(ans, recur(i + 1 , j - A.get(i), T, A)); // save and return dp value return dp[i][j + 10000 ] = ans; } // Function to check whether given // Coordinates (X, Y) is reachable // from origin public static void isReachable( int [] A, int N, int X, int Y) { // creating two different arrays A1 // for solving X coordinate and A2 // for solving Y coordinate Vector<Integer> A1 = new Vector<>(); Vector<Integer> A2 = new Vector<>(); // filling both the A1 and A2 for ( int i = 0 ; i < N; i++) { if (i % 2 == 0 ) A1.add(A[i]); else A2.add(A[i]); } // filling dp table with -1 for ( int [] row : dp) Arrays.fill(row, - 1 ); // to check whether Reaching X // coordinate is possible by moves // {A[1], A[3], A[5], A[7], .....} int isPossibleX = recur( 0 , 0 , X, A1); // filling dp table with -1 for ( int [] row : dp) Arrays.fill(row, - 1 ); // to check whether Reaching Y // coordinate is possible by moves // {A[2], A[4], A[6], ........} int isPossibleY = recur( 0 , 0 , Y, A2); // if reaching X and Y coordinates Both // are possible then only reaching on (X, Y) // is possible by player if (isPossibleX == 1 && isPossibleY == 1 ) System.out.println( "Yes" ); else System.out.println( "No" ); } public static void main(String[] args) { // Input 1 int [] A = { 2 , 1 , 3 }; int N = A.length; int X = - 1 , Y = 1 ; // Function Call isReachable(A, N, X, Y); // Input 2 int [] A1 = { 1 , 2 , 3 , 4 }; int N1 = A1.length; int X1 = 5 , Y1 = 5 ; // Function Call isReachable(A1, N1, X1, Y1); } } // This code is contributed by lokesh. |
Python3
# Python3 code to implement the approach # dp table initialized with -1 dp = [[ - 1 for j in range ( 20001 )] for i in range ( 501 )] # recursive function to tell whether # given coordinate (X, Y) is reachable # or not from origin def recur(i, j, T, A): # base case if i = = len (A): # if T is possible return 1 if j = = T: return 1 else : return 0 # if answer for current state is already # calculated then just return dp[i][j] # + 10000 is offset value to also include # negative numbers in states if dp[i][j + 10000 ] ! = - 1 : return dp[i][j + 10000 ] ans = 0 # calling recursive function to move Right # in case of X coordinate or UP in case of # Y coordinate by distance A[i] ans = max (ans, recur(i + 1 , j + A[i], T, A)) # calling recursive function to move Left # in case of X coordinate or Down in case of # Y coordinate by distance A[i] ans = max (ans, recur(i + 1 , j - A[i], T, A)) # save and return dp value dp[i][j + 10000 ] = ans return dp[i][j + 10000 ] # Function to check whether given # Coordinates (X, Y) is reachable # from origin def isReachable(A, N, X, Y): # creating two different arrays A1 # for solving X coordinate and A2 # for solving Y coordinate A1 = [] A2 = [] # filling both the A1 and A2 for i in range (N): if i % 2 = = 0 : A1.append(A[i]) else : A2.append(A[i]) # to check whether Reaching X # coordinate is possible by moves # {A[1], A[3], A[5], A[7], .....} isPossibleX = recur( 0 , 0 , X, A1) # to check whether Reaching Y # coordinate is possible by moves # {A[2], A[4], A[6], ........} isPossibleY = recur( 0 , 0 , Y, A2) # if reaching X and Y coordinates Both # are possible then only reaching on (X, Y) # is possible by player if isPossibleX and isPossibleY: print ( "Yes" ) else : print ( "No" ) # Driver Code # Input 1 A = [ 2 , 1 , 3 ] N = len (A) X = - 1 Y = 1 # Function Call isReachable(A, N, X, Y) dp = [[ - 1 for j in range ( 20001 )] for i in range ( 501 )] # Input 2 A1 = [ 1 , 2 , 3 , 4 ] N1 = len (A1) X1 = 5 Y1 = 5 # Function Call isReachable(A1, N1, X1, Y1) # This code is contributed by Potta Lokesh |
Javascript
// Javascript code to implement the approach // dp table initialized with - 1 //let dp[501][20001]; let dp= new Array(501); for (let i=0; i<501; i++) dp[i]= new Array(20001); // recursive function to tell whether // given coordinate (X, Y) is reachable // or not from origin function recur(i, j, T, A) { // base case if (i == A.length) { // if T is possible return 1 if (j == T) return 1; else return 0; } // if answer for current state is already // calculated then just return dp[i][j] // + 10000 is offset value to also include // negative numbers in states if (dp[i][j + 10000] != -1) return dp[i][j + 10000]; let ans = 0; // calling recursive function to move Right // in case of X coordinate or UP in case of // Y coordinate by distance A[i] ans = Math.max(ans, recur(i + 1, j + A[i], T, A)); // calling recursive function to move Left // in case of X coordinate or Down in case of // Y coordinate by distance A[i] ans = Math.max(ans, recur(i + 1, j - A[i], T, A)); // save and return dp value return dp[i][j + 10000] = ans; } // Function to check whether given // Coordinates (X, Y) is reachable // from origin function isReachable(A, N, X, Y) { // creating two different arrays A1 // for solving X coordinate and A2 // for solving Y coordinate let A1=[], A2=[]; // filling both the A1 and A2 for (let i = 0; i < N; i++) { if (i % 2 == 0) A1.push(A[i]); else A2.push(A[i]); } // filling dp table with -1 for (let i=0; i<501; i++) for (let j=0; j<20001; j++) dp[i][j]=-1; // to check whether Reaching X // coordinate is possible by moves // {A[1], A[3], A[5], A[7], .....} let isPossibleX = recur(0, 0, X, A1); // filling dp table with -1 for (let i=0; i<501; i++) for (let j=0; j<20001; j++) dp[i][j]=-1; // to check whether Reaching Y // coordinate is possible by moves // {A[2], A[4], A[6], ........} let isPossibleY = recur(0, 0, Y, A2); // if reaching X and Y coordinates Both // are possible then only reaching on (X, Y) // is possible by player if (isPossibleX && isPossibleY) document.write( "Yes" ); else document.write( "No" ); } // Driver Code // Input 1 let A = [ 2, 1, 3 ]; let N = A.length; let X = -1, Y = 1; // Function Call isReachable(A, N, X, Y); document.write( "<br>" ); // Input 2 let A1 = [ 1, 2, 3, 4 ]; let N1 = A1.length; let X1 = 5, Y1 = 5; // Function Call isReachable(A1, N1, X1, Y1); |
C#
using System; using System.Collections.Generic; class GFG { // dp table initialized with - 1 static int [, ] dp = new int [501, 20001]; // recursive function to tell whether // given coordinate (X, Y) is reachable // or not from origin static int recur( int i, int j, int T, List< int > A) { // base case if (i == A.Count) { // if T is possible return 1 if (j == T) return 1; else return 0; } // if answer for current state is already // calculated then just return dp[i][j] // + 10000 is offset value to also include // negative numbers in states if (dp[i, j + 10000] != -1) return dp[i, j + 10000]; int ans = 0; // calling recursive function to move Right // in case of X coordinate or UP in case of // Y coordinate by distance A[i] ans = Math.Max(ans, recur(i + 1, j + A[i], T, A)); // calling recursive function to move Left // in case of X coordinate or Down in case of // Y coordinate by distance A[i] ans = Math.Max(ans, recur(i + 1, j - A[i], T, A)); // save and return dp value return dp[i, j + 10000] = ans; } static void isReachable( int [] A, int N, int X, int Y) { // creating two different lists A1 // for solving X coordinate and A2 // for solving Y coordinate List< int > A1 = new List< int >(); List< int > A2 = new List< int >(); // filling both the A1 and A2 for ( int i = 0; i < N; i++) { if (i % 2 == 0) A1.Add(A[i]); else A2.Add(A[i]); } for ( int i = 0; i < 501; i++) for ( int j = 0; j < 20001; j++) dp[i, j] = -1; // to check whether Reaching X // coordinate is possible by moves // {A[1], A[3], A[5], A[7], .....} int isPossibleX = recur(0, 0, X, A1); for ( int i = 0; i < 501; i++) for ( int j = 0; j < 20001; j++) dp[i, j] = -1; // to check whether Reaching Y // coordinate is possible by moves // {A[2], A[4], A[6], ........} int isPossibleY = recur(0, 0, Y, A2); // if reaching X and Y coordinates Both // are possible then only reaching on (X, Y) // is possible by player if (isPossibleX == 1 && isPossibleY == 1) Console.WriteLine( "Yes" ); else Console.WriteLine( "No" ); } static void Main( string [] args) { // Input 1 int [] A = { 2, 1, 3 }; int N = A.Length; int X = -1, Y = 1; // Function Call isReachable(A, N, X, Y); // Input 2 int [] A1 = { 1, 2, 3, 4 }; int N1 = A1.Length; int X1 = 5, Y1 = 5; // Function Call isReachable(A1, N1, X1, Y1); } } |
Yes No
Complexity Analysis:
Time Complexity: O(N * AMax)
Auxiliary Space: O(N * AMax)
Where AMax is Maximum value in array A[]
Related Articles :
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!