Rahul and Ankit are the only two waiters in Royal Restaurant. Today, the restaurant received N orders. The amount of tips may differ when handled by different waiters, if Rahul takes the ith order, he would be tipped Ai rupees and if Ankit takes this order, the tip would be Bi rupees.
In order to maximize the total tip value they decided to distribute the order among themselves. One order will be handled by one person only. Also, due to time constraints, Rahul cannot take more than X orders and Ankit cannot take more than Y orders. It is guaranteed that X + Y is greater than or equal to N, which means that all the orders can be handled by either Rahul or Ankit. Find out the maximum possible amount of total tip money after processing all the orders.
Examples:
Input: A[] = {1, 2, 3, 4, 5}, B[] = {5, 4, 3, 2, 1}, X = 3, Y = 3
Output: 21
1st, 2nd and 3rd orders are taken by waiter Y.
4th and 5th orders are taken by waiter X.Input: A[] = {2, 2, 2}, B[] = {3, 3, 3}, X = 3, Y = 3
Output: 9
Recursive solution: We can move in a recursive way to calculate the maximum amount order to be taken in such a manner
that the total tip would be maximum. The solution would contain 4 cases:
- i == n: When this is reached it means all orders are taken. So return 0 and move back.
- X ? 0: When waiter X cannot take more orders.
- Y ? 0: When waiter Y cannot take more orders.
- max(Orders(X), Orders(Y)): We need to return the maximum of tip when orders taken by both X and Y.
Below is the implementation of the above approach:
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std;
int n;
// Recursive function to calculate sum of // maximum tip order taken by X and Y int solve( int i, int X, int Y,
int a[], int b[], int n)
{ // When all orders have been taken
if (i == n)
return 0;
// When X cannot take more orders
if (X <= 0)
return b[i] + solve(i + 1, X,
Y - 1, a, b, n);
// When Y cannot take more orders
if (Y <= 0)
return a[i] + solve(i + 1, X - 1,
Y, a, b, n);
// When both can take order
// calculate maximum out of two
else
return max(a[i] + solve(i + 1, X - 1,
Y, a, b, n),
b[i] + solve(i + 1, X,
Y - 1, a, b, n));
} // Driver code int main()
{ int a[] = { 1, 2, 3, 4, 5 };
int b[] = { 5, 4, 3, 2, 1 };
int n = sizeof (a) / sizeof (a[0]);
int x = 3, y = 3;
cout << solve(0, x, y, a, b, n);
return 0;
} |
// Java implementation for the above approach import java.io.*;
class GFG
{ static int n;
// Recursive function to calculate sum of
// maximum tip order taken by X and Y
static int solve( int i, int X, int Y, int a[], int b[],
int n)
{
// When all orders have been taken
if (i == n)
return 0 ;
// When X cannot take more orders
if (X <= 0 )
return b[i] + solve(i + 1 , X, Y - 1 , a, b, n);
// When Y cannot take more orders
if (Y <= 0 )
return a[i] + solve(i + 1 , X - 1 , Y, a, b, n);
// When both can take order
// calculate maximum out of two
else
return Math.max(
a[i] + solve(i + 1 , X - 1 , Y, a, b, n),
b[i] + solve(i + 1 , X, Y - 1 , a, b, n));
}
// Driver code
public static void main(String[] args)
{
int a[] = { 1 , 2 , 3 , 4 , 5 };
int b[] = { 5 , 4 , 3 , 2 , 1 };
int n = a.length;
int x = 3 , y = 3 ;
System.out.println(solve( 0 , x, y, a, b, n));
}
} // This code is contributed by Potta Lokesh |
# Python3 program for the above approach # Recursive function to calculate sum of # maximum tip order taken by X and Y def solve(i, X, Y,
a, b, n) :
# When all orders have been taken
if (i = = n):
return 0
# When X cannot take more orders
if (X < = 0 ):
return (b[i] + solve(i + 1 , X,
Y - 1 , a, b, n))
# When Y cannot take more orders
if (Y < = 0 ):
return (a[i] + solve(i + 1 , X - 1 ,
Y, a, b, n))
# When both can take order
# calculate maximum out of two
else :
return max (a[i] + solve(i + 1 , X - 1 ,
Y, a, b, n),
b[i] + solve(i + 1 , X,
Y - 1 , a, b, n))
# Driver code a = [ 1 , 2 , 3 , 4 , 5 ]
b = [ 5 , 4 , 3 , 2 , 1 ]
n = len (a)
x = 3
y = 3
print (solve( 0 , x, y, a, b, n))
# This code is contributed by splevel62. |
// C# program for the above approach using System;
class GFG{
static int n;
// Recursive function to calculate sum of // maximum tip order taken by X and Y static int solve( int i, int X, int Y,
int [] a, int [] b, int n)
{ // When all orders have been taken
if (i == n)
return 0;
// When X cannot take more orders
if (X <= 0)
return b[i] + solve(i + 1, X, Y - 1,
a, b, n);
// When Y cannot take more orders
if (Y <= 0)
return a[i] + solve(i + 1, X - 1, Y,
a, b, n);
// When both can take order
// calculate maximum out of two
else
return Math.Max(
a[i] + solve(i + 1, X - 1, Y, a, b, n),
b[i] + solve(i + 1, X, Y - 1, a, b, n));
} // Driver Code public static void Main(String[] args)
{ int [] a = { 1, 2, 3, 4, 5 };
int [] b = { 5, 4, 3, 2, 1 };
// int n = a.Length;
int x = 3, y = 3;
Console.Write(solve(0, x, y, a, b, n));
} } // This code is contributed by sanjoy_62 |
<script> // JavaScript implementation of the approach let n; // Recursive function to calculate sum of // maximum tip order taken by X and Y function solve(i, X, Y, a, b, n) {
// When all orders have been taken
if (i == n) return 0;
// When X cannot take more orders
if (X <= 0) return b[i] + solve(i + 1, X, Y - 1, a, b, n);
// When Y cannot take more orders
if (Y <= 0) return a[i] + solve(i + 1, X - 1, Y, a, b, n);
// When both can take order
// calculate maximum out of two
else
return Math.max(
a[i] + solve(i + 1, X - 1, Y, a, b, n),
b[i] + solve(i + 1, X, Y - 1, a, b, n)
);
} // Driver code let a = [1, 2, 3, 4, 5]; let b = [5, 4, 3, 2, 1]; n = a.length; let x = 3, y = 3;
document.write(solve(0, x, y, a, b, n)); </script> |
21
Time Complexity: O(2n)
DP-based approach: The optimal substructure of the previous approach contains repetitions which could be avoided by storing previously calculated tips in the array. This would reduce the time complexity to O(n).
Below is the implementation of the above approach:
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std;
// Global Variables int N, X, Y;
vector< int > A_right_sum, B_right_sum;
vector<unordered_map< int ,
unordered_map< int , int > > >
mem;
vector<unordered_map< int ,
unordered_map< int , bool > > >
vis;
// Function to check if visited before bool get_vis_val( int i, int x, int y)
{ if (i == N)
return true ;
return vis[i][x][y];
} // Function to return the tip value int get_mem_val( int i, int x, int y)
{ if (i == N)
return 0;
return mem[i][x][y];
} // Function to calculate the maximum tip possible void find_ans( int i, int x, int y,
vector< int > A, vector< int > B)
{ // If already visited
if (get_vis_val(i, x, y))
return ;
vis[i][x][y] = true ;
// If X cannot take more orders
if (x == 0) {
mem[i][x][y] = B_right_sum[i];
}
// If Y cannot take more orders
else if (y == 0) {
mem[i][x][y] = A_right_sum[i];
}
// If both can take orders then
// calculate the maximum of two
else {
find_ans(i + 1, x - 1, y, A, B);
find_ans(i + 1, x, y - 1, A, B);
mem[i][x][y]
= max(get_mem_val(i + 1, x - 1, y)
+ A[i],
get_mem_val(i + 1, x, y - 1)
+ B[i]);
}
} // Driver code int main()
{ int a[] = { 1, 2, 3, 4, 5 };
int b[] = { 5, 4, 3, 2, 1 };
N = sizeof (a) / sizeof (a[0]);
X = 3;
Y = 3;
// Vector containing the tips of waiter X
vector< int > A(a, a + N);
// Vector containing the tips of waiter Y
vector< int > B(b, b + N);
// Memory allocation and clearing
// of previous caches
mem.clear();
mem.resize(N + 1);
vis.clear();
vis.resize(N + 1);
A_right_sum.resize(N);
B_right_sum.resize(N);
A_right_sum[N - 1] = A[N - 1];
B_right_sum[N - 1] = B[N - 1];
// Precalculation of sums
// of tip at each ith order
for ( int i = N - 2; i >= 0; i--) {
A_right_sum[i]
= A_right_sum[i + 1] + A[i];
B_right_sum[i]
= B_right_sum[i + 1] + B[i];
}
// Bottom up dp based solution
find_ans(0, X, Y, A, B);
// Final ans stored in mem[0][X][Y]
cout << get_mem_val(0, X, Y) << endl;
return 0;
} |
// Java program for the above approach import java.util.*;
public class Main {
static int N, X, Y;
static List<Map<Integer, Map<Integer, Integer>>> mem = new ArrayList<>();
static List<Map<Integer, Map<Integer, Boolean>>> vis = new ArrayList<>();
static List<Integer> A_right_sum = new ArrayList<>();
static List<Integer> B_right_sum = new ArrayList<>();
// Function to check if visited before
public static boolean get_vis_val( int i, int x, int y) {
if (i == N)
return true ;
return vis.get(i).get(x).get(y);
}
// Function to return the tip value
public static int get_mem_val( int i, int x, int y) {
if (i == N)
return 0 ;
return mem.get(i).get(x).get(y);
}
// Function to calculate the maximum tip possible
public static void find_ans( int i, int x, int y, List<Integer> A, List<Integer> B) {
// If already visited
if (get_vis_val(i, x, y))
return ;
vis.get(i).get(x).put(y, true );
// If X cannot take more orders
if (x == 0 ) {
mem.get(i).get(x).put(y, B_right_sum.get(i));
}
// If Y cannot take more orders
else if (y == 0 ) {
mem.get(i).get(x).put(y, A_right_sum.get(i));
}
// If both can take orders then
// calculate the maximum of two
else {
find_ans(i + 1 , x - 1 , y, A, B);
find_ans(i + 1 , x, y - 1 , A, B);
mem.get(i).get(x).put(y,
Math.max(get_mem_val(i + 1 , x - 1 , y) + A.get(i),
get_mem_val(i + 1 , x, y - 1 ) + B.get(i)));
}
}
// Driver Code
public static void main(String[] args) {
int [] a = { 1 , 2 , 3 , 4 , 5 };
int [] b = { 5 , 4 , 3 , 2 , 1 };
N = a.length;
X = 3 ;
Y = 3 ;
// Vector containing the tips of waiter X
List<Integer> A = new ArrayList<>();
// Vector containing the tips of waiter Y
List<Integer> B = new ArrayList<>();
for ( int i = 0 ; i < N; i++) {
A.add(a[i]);
B.add(b[i]);
}
for ( int i = 0 ; i <= N; i++) {
mem.add( new HashMap<>());
vis.add( new HashMap<>());
for ( int j = 0 ; j <= X; j++) {
mem.get(i).put(j, new HashMap<>());
vis.get(i).put(j, new HashMap<>());
for ( int k = 0 ; k <= Y; k++) {
mem.get(i).get(j).put(k, 0 );
vis.get(i).get(j).put(k, false );
}
}
}
A_right_sum.add(A.get(N - 1 ));
B_right_sum.add(B.get(N - 1 ));
// Precalculation of sums
// of tip at each ith order
for ( int i = N - 2 ; i >= 0 ; i--) {
A_right_sum.add( 0 , A_right_sum.get( 0 ) + A.get(i));
B_right_sum.add( 0 , B_right_sum.get( 0 ) + B.get(i));
}
// Bottom up dp based solution
find_ans( 0 , X, Y, A, B);
// Final ans stored in mem[0][X][Y]
System.out.println(get_mem_val( 0 , X, Y));
}
} // This code is contributed by princekumaras |
# Python program for the above approach: ## Global Variables N = 0
X = 0
Y = 0
A_right_sum = []
B_right_sum = []
# vector<unordered_map<int, unordered_map<int, int> > > mem; # vector<unordered_map<int, unordered_map<int, bool> > > vis; mem = []
vis = []
## Function to check if visited before def get_vis_val(i, x, y):
if (i = = N):
return True
if (x not in vis[i]):
return False
if (y not in vis[i][x]):
return False
return vis[i][x][y]
## Function to return the tip value def get_mem_val(i, x, y):
if (i = = N):
return 0
if (x not in mem[i]):
return 0
if (y not in mem[i][x]):
return 0
return mem[i][x][y]
## Function to calculate the maximum tip possible def find_ans(i, x, y, A, B):
## If already visited
if (get_vis_val(i, x, y)):
return ;
if (x not in vis[i]):
vis[i][x] = {}
vis[i][x][y] = True
## If X cannot take more orders
if (x = = 0 ):
if (x not in mem[i]):
mem[i][x] = {}
mem[i][x][y] = B_right_sum[i]
## If Y cannot take more orders
elif (y = = 0 ):
if (x not in mem[i]):
mem[i][x] = {}
mem[i][x][y] = A_right_sum[i]
## If both can take orders then
## calculate the maximum of two
else :
find_ans(i + 1 , x - 1 , y, A, B)
find_ans(i + 1 , x, y - 1 , A, B)
if (x not in mem[i]):
mem[i][x] = {}
mem[i][x][y] = max (get_mem_val(i + 1 , x - 1 , y) + A[i], get_mem_val(i + 1 , x, y - 1 ) + B[i])
## Driver code if __name__ = = '__main__' :
a = [ 1 , 2 , 3 , 4 , 5 ]
b = [ 5 , 4 , 3 , 2 , 1 ]
N = len (a)
X = 3
Y = 3
## Vector containing the tips of waiter X
A = []
for i in range ( 0 , N):
A.append(a[i])
## Vector containing the tips of waiter Y
B = []
for i in range ( 0 , N):
B.append(b[i])
## Memory allocation and clearing
## of previous caches
mem.clear();
for i in range ( 0 , N + 1 ):
mem.append({})
vis.clear();
for i in range ( 0 , N + 1 ):
vis.append({})
for i in range ( 0 , N):
A_right_sum.append( 0 );
B_right_sum.append( 0 );
A_right_sum[N - 1 ] = A[N - 1 ];
B_right_sum[N - 1 ] = B[N - 1 ];
## Precalculation of sums
## of tip at each ith order
for i in range (N - 2 , - 1 , - 1 ):
A_right_sum[i] = A_right_sum[i + 1 ] + A[i]
B_right_sum[i] = B_right_sum[i + 1 ] + B[i]
## Bottom up dp based solution
find_ans( 0 , X, Y, A, B);
## Final ans stored in mem[0][X][Y]
print (get_mem_val( 0 , X, Y))
# This code is contributed by subhamgoyal2014.
|
using System;
using System.Collections.Generic;
class Program
{ static int N, X, Y;
static List<Dictionary< int , Dictionary< int , int >>> mem = new List<Dictionary< int , Dictionary< int , int >>>();
static List<Dictionary< int , Dictionary< int , bool >>> vis = new List<Dictionary< int , Dictionary< int , bool >>>();
static List< int > A_right_sum = new List< int >();
static List< int > B_right_sum = new List< int >();
// Function to check if visited before
public static bool GetVisValue( int i, int x, int y)
{
if (i == N)
return true ;
return vis[i][x][y];
}
// Function to return the tip value
public static int GetMemValue( int i, int x, int y)
{
if (i == N)
return 0;
return mem[i][x][y];
}
// Function to calculate the maximum tip possible
public static void FindAns( int i, int x, int y, List< int > A, List< int > B)
{
// If already visited
if (GetVisValue(i, x, y))
return ;
vis[i][x][y] = true ;
// If X cannot take more orders
if (x == 0)
{
mem[i][x][y] = B_right_sum[i];
}
// If Y cannot take more orders
else if (y == 0)
{
mem[i][x][y] = A_right_sum[i];
}
// If both can take orders then
// calculate the maximum of two
else
{
FindAns(i + 1, x - 1, y, A, B);
FindAns(i + 1, x, y - 1, A, B);
mem[i][x][y] = Math.Max(GetMemValue(i + 1, x - 1, y) + A[i],
GetMemValue(i + 1, x, y - 1) + B[i]);
}
}
// Driver Code
public static void Main()
{
int [] a = { 1, 2, 3, 4, 5 };
int [] b = { 5, 4, 3, 2, 1 };
N = a.Length;
X = 3;
Y = 3;
// Vector containing the tips of waiter X
List< int > A = new List< int >(a);
// Vector containing the tips of waiter Y
List< int > B = new List< int >(b);
for ( int i = 0; i <= N; i++)
{
mem.Add( new Dictionary< int , Dictionary< int , int >>());
vis.Add( new Dictionary< int , Dictionary< int , bool >>());
for ( int j = 0; j <= X; j++)
{
mem[i].Add(j, new Dictionary< int , int >());
vis[i].Add(j, new Dictionary< int , bool >());
for ( int k = 0; k <= Y; k++)
{
mem[i][j].Add(k, 0);
vis[i][j].Add(k, false );
}
}
}
A_right_sum.Insert(0, A[N - 1]);
B_right_sum.Insert(0, B[N - 1]);
// Precalculation of sums
// of tip at each ith order
for ( int i = N - 2; i >= 0; i--)
{
A_right_sum.Insert(0, A_right_sum[0] + A[i]);
B_right_sum.Insert(0, B_right_sum[0] + B[i]);
}
// Bottom up dp based solution
FindAns(0, X, Y, A, B);
// Final ans stored in mem[0][X][Y]
Console.WriteLine(GetMemValue(0, X, Y));
}
} |
// JavaScript implementation of the approach // Global Variables let N, X, Y; let A_right_sum, B_right_sum; let mem, vis; // Function to check if visited before function getVisVal(i, x, y) {
if (i === N) {
return true ;
}
return vis[i][x][y];
} // Function to return the tip value function getMemVal(i, x, y) {
if (i === N) {
return 0;
}
return mem[i][x][y];
} // Function to calculate the maximum tip possible function findAns(i, x, y, A, B) {
// If already visited
if (getVisVal(i, x, y)) {
return ;
}
vis[i][x][y] = true ;
// If X cannot take more orders
if (x === 0) {
mem[i][x][y] = B_right_sum[i];
}
// If Y cannot take more orders
else if (y === 0) {
mem[i][x][y] = A_right_sum[i];
}
// If both can take orders then calculate the maximum of two
else {
findAns(i + 1, x - 1, y, A, B);
findAns(i + 1, x, y - 1, A, B);
mem[i][x][y] = Math.max(
getMemVal(i + 1, x - 1, y) + A[i],
getMemVal(i + 1, x, y - 1) + B[i]
);
}
} // Driver code function main() {
const a = [1, 2, 3, 4, 5];
const b = [5, 4, 3, 2, 1];
N = a.length;
X = 3;
Y = 3;
// Vector containing the tips of waiter X
const A = [...a];
// Vector containing the tips of waiter Y
const B = [...b];
// Memory allocation and clearing of previous caches
mem = new Array(N + 1).fill().map(() => new Array(X + 1).fill().map(() => new Array(Y + 1).fill(0)));
vis = new Array(N + 1).fill().map(() => new Array(X + 1).fill().map(() => new Array(Y + 1).fill( false )));
A_right_sum = new Array(N);
B_right_sum = new Array(N);
A_right_sum[N - 1] = A[N - 1];
B_right_sum[N - 1] = B[N - 1];
// Precalculation of sums of tip at each ith order
for (let i = N - 2; i >= 0; i--) {
A_right_sum[i] = A_right_sum[i + 1] + A[i];
B_right_sum[i] = B_right_sum[i + 1] + B[i];
}
// Bottom up dp based solution
findAns(0, X, Y, A, B);
// Final ans stored in mem[0][X][Y]
console.log(getMemVal(0, X, Y));
} // Execute the main function main(); |
21
Time Complexity: O(N)
Space Complexity: O(N2)