Skip to content
Related Articles

Related Articles

Improve Article

Maximum Tip Calculator

  • Difficulty Level : Medium
  • Last Updated : 05 Aug, 2021

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:

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:  



  1. i == n: When this is reached it means all orders are taken. So return 0 and move back.
  2. X ≤ 0: When waiter X cannot take more orders.
  3. Y ≤ 0: When waiter Y cannot take more orders.
  4. 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++




// 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




// 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




# 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#




// 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

Javascript




<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>
Output: 
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++




// 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;
}
Output: 
21

 

Time Complexity: O(N) 
Space Complexity: O(N2)
 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up
Recommended Articles
Page :