Given array A[] and B[] both having size N. Select minimum number indexes so that sum of elements from A[] on those indexes and the sum of elements of B[] on the same indexes are at least X and Y respectively. Print the count of the minimum number of indexes else if it is not possible print – 1.
Examples:
Input: A[] = {2, 3, 2}, B[] = {1, 4, 3}, X = 5, Y = 6 Output: 2 Explanation: Selecting the 2nd and 3rd index we will get the sum 3 + 2 = 5 in the first array and 4 + 3 = 7 in the second array. 5 ≥ X and 7 ≥ Y so both the conditions are true. Hence answer will be 2.
Input: A[] = {3, 2, 2}, B[] = {4, 3, 1}, X = 8, Y = 8 Output: -1 Explanation: Even if we select all the indexes then also the sum of the first array will never be greater than equal to X. Hence -1 will be the answer that is not possible
Naive approach: The basic way to solve the problem is as follows:
The basic way to solve this problem is to generate all possible combinations by using a recursive approach.
Time Complexity: O(2N) Auxiliary Space: O(1)
Efficient Approach: The above approach can be optimized based on the following idea:
Dynamic programming can be used to solve this problem
Naive DP:
- dp[i][j][k] represents the minimum number of indexes selected from the first i indexes so that sum of the first array on those indexes is equal to j and the second array on the same indexes is equal to k.
- dp[i][j][k] = min(dp[i + 1][j + A[i]][k + B[i]] + 1, dp[i + 1][j][k]);
The problem with this DP approach is that we need to make a dp array of size about the total maximum sum of the first array and the total maximum sum of the second array which is not possible.
Optimized DP:
- dp[i][j][k] represents the minimum number of indexes subtracted from the first array from X and the second array from Y so that they are both zero.
- dp[i][j][k] = min(dp[i + 1][j – A[i]][k – B[i]] + 1, dp[i + 1][j][k]
It can be observed that the recursive function is called exponential times. That means that some states are called repeatedly. So the idea is to store the value of each state. This can be done using by store the value of a state and whenever the function is called, return the stored value without computing again.
Follow the steps below to solve the problem:
- Create a recursive function that takes three parameters i representing the index that is to be chosen, j representing leftover X, and k representing leftover Y.
- Call the recursive function for both choosing the current index and not choosing the current index.
- Base case if both j and k are 0 then return 0 else return an invalid number.
- Create a 3d array of dp[N][X][Y] initially filled with -1.
- If the answer for a particular state is computed then save it in dp[i][j][k].
- If the answer for a particular state is already computed then just return dp[i][j][k].
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int dp[301][301][301];
int recur( int i, int j, int k, int A[], int B[], int N)
{
if (i == N) {
if (j == 0 and k == 0)
return 0;
else
return 1e9;
}
if (dp[i][j][k] != -1)
return dp[i][j][k];
int ans = INT_MAX;
ans = min(ans, recur(i + 1, j, k, A, B, N));
ans = min(ans, recur(i + 1, max(0, j - A[i]),
max(0, k - B[i]), A, B, N)
+ 1);
return dp[i][j][k] = ans;
}
int findMinimumCount( int A[], int B[], int N, int X, int Y)
{
memset (dp, -1, sizeof (dp));
int ans = recur(0, X, Y, A, B, N);
if (ans == 1e9)
return -1;
else
return ans;
}
int main()
{
int A[] = { 2, 3, 2 }, B[] = { 1, 4, 3 }, X = 5, Y = 6;
int N = sizeof (A) / sizeof (A[0]);
cout << findMinimumCount(A, B, N, X, Y) << endl;
int A1[] = { 3, 2, 2 }, B1[] = { 4, 3, 1 }, X1 = 8,
Y1 = 8;
int N1 = sizeof (A1) / sizeof (A1[0]);
cout << findMinimumCount(A1, B1, N1, X1, Y1) << endl;
return 0;
}
|
Java
import java.io.*;
import java.util.Arrays;
class GFG
{
static int dp[][][] = new int [ 301 ][ 301 ][ 301 ];
public static int recur( int i, int j, int k, int A[],
int B[], int N)
{
if (i == N) {
if (j == 0 && k == 0 )
return 0 ;
else
return 1000000000 ;
}
if (dp[i][j][k] != - 1 )
return dp[i][j][k];
int ans = Integer.MAX_VALUE;
ans = Math.min(ans, recur(i + 1 , j, k, A, B, N));
ans = Math.min(ans,
recur(i + 1 , Math.max( 0 , j - A[i]),
Math.max( 0 , k - B[i]), A, B, N)
+ 1 );
return dp[i][j][k] = ans;
}
public static int findMinimumCount( int A[], int B[],
int N, int X, int Y)
{
for ( int [][] row : dp) {
for ( int [] rowColumn : row) {
Arrays.fill(rowColumn, - 1 );
}
}
int ans = recur( 0 , X, Y, A, B, N);
if (ans == 1000000000 )
return - 1 ;
else
return ans;
}
public static void main(String[] args)
{
int A[] = { 2 , 3 , 2 };
int B[] = { 1 , 4 , 3 };
int X = 5 ;
int Y = 6 ;
int N = A.length;
System.out.println(findMinimumCount(A, B, N, X, Y));
int A1[] = { 3 , 2 , 2 };
int B1[] = { 4 , 3 , 1 };
int X1 = 8 ;
int Y1 = 8 ;
int N1 = A1.length;
System.out.println(
findMinimumCount(A1, B1, N1, X1, Y1));
}
}
|
Python3
import math
dp = [[[ - 1 for _ in range ( 301 )] for _ in range ( 301 )] for _ in range ( 301 )]
def recur(i, j, k, A, B, N):
if i = = N:
if j = = 0 and k = = 0 :
return 0
else :
return 1000000000
if dp[i][j][k] ! = - 1 :
return dp[i][j][k]
ans = math.inf
ans = min (ans, recur(i + 1 , j, k, A, B, N))
ans = min (ans, recur(i + 1 , max ( 0 , j - A[i]),
max ( 0 , k - B[i]), A, B, N)
+ 1 )
dp[i][j][k] = ans
return ans
def findMinimumCount(A, B, N, X, Y):
ans = recur( 0 , X, Y, A, B, N)
if ans = = 1000000000 :
return - 1
else :
return ans
A = [ 2 , 3 , 2 ]
B = [ 1 , 4 , 3 ]
X = 5
Y = 6
N = len (A)
print (findMinimumCount(A, B, N, X, Y))
A1 = [ 3 , 2 , 2 ]
B1 = [ 4 , 3 , 1 ]
X1 = 8
Y1 = 8
N1 = len (A1)
print (findMinimumCount(A1, B1, N1, X1, Y1))
|
C#
using System;
using System.Linq;
public class GFG {
static int [, , ] dp = new int [301, 301, 301];
public static int recur( int i, int j, int k, int [] A,
int [] B, int N)
{
if (i == N) {
if (j == 0 && k == 0)
return 0;
else
return 1000000000;
}
if (dp[i, j, k] != -1)
return dp[i, j, k];
int ans = int .MaxValue;
ans = Math.Min(ans, recur(i + 1, j, k, A, B, N));
ans = Math.Min(ans,
recur(i + 1, Math.Max(0, j - A[i]),
Math.Max(0, k - B[i]), A, B, N)
+ 1);
return dp[i, j, k] = ans;
}
public static int findMinimumCount( int [] A, int [] B,
int N, int X, int Y)
{
for ( int i = 0; i < dp.GetLength(0); i++) {
for ( int j = 0; j < dp.GetLength(1); j++) {
for ( int k = 0; k < dp.GetLength(2); k++) {
dp[i, j, k] = -1;
}
}
}
int ans = recur(0, X, Y, A, B, N);
if (ans == 1000000000)
return -1;
else
return ans;
}
static public void Main()
{
int [] A = { 2, 3, 2 };
int [] B = { 1, 4, 3 };
int X = 5;
int Y = 6;
int N = A.Length;
Console.WriteLine(findMinimumCount(A, B, N, X, Y));
int [] A1 = { 3, 2, 2 };
int [] B1 = { 4, 3, 1 };
int X1 = 8;
int Y1 = 8;
int N1 = A1.Length;
Console.WriteLine(
findMinimumCount(A1, B1, N1, X1, Y1));
}
}
|
Javascript
let dp = new Array(301);
for (let i=0; i<301; i++){
dp[i]= new Array(301);
for (let j=0; j<301; j++){
dp[i][j]= new Array(301).fill(-1);
}
}
function recur(i, j, k, A, B, N)
{
if (i == N) {
if (j == 0 && k == 0)
return 0;
else
return 1e9;
}
if (dp[i][j][k] != -1)
return dp[i][j][k];
let ans = Number.MAX_SAFE_INTEGER;
ans = Math.min(ans, recur(i + 1, j, k, A, B, N));
ans = Math.min(ans, recur(i + 1, Math.max(0, j - A[i]),
Math.max(0, k - B[i]), A, B, N)
+ 1);
return dp[i][j][k] = ans;
}
function findMinimumCount(A, B, N, X, Y)
{
let ans = recur(0, X, Y, A, B, N);
if (ans == 1e9)
return -1;
else
return ans;
}
let A = [2, 3, 2], B = [ 1, 4, 3 ], X = 5, Y = 6;
let N = A.length;
document.write(findMinimumCount(A, B, N, X, Y));
document.write( "<br>" );
let A1 = [ 3, 2, 2 ], B1 = [4, 3, 1], X1 = 8, Y1 = 8;
let N1 = A1.length;
document.write(findMinimumCount(A1, B1, N1, X1, Y1))
|
Time Complexity: O(N * X * Y) Auxiliary Space: O(N * X * Y)
Related Articles:
|