Maximum profit using M money and reducing half price of at most K stocks
Given the cost[] and profit[] of N stocks and K tickets, the task is to find the maximum total profit that can be obtained from M initial amount of money using K tickets.
Note: A ticket can be used to reduce the cost of any stock to half of the original price and on a particular stock, a ticket can be used only once.
Examples:
Input: N = 3, cost[] = {2, 4, 5}, profit[] = {20, 17, 15}, K = 1, M = 4
Output: 37
Explanation: The most optimal case is when we take the 1st stock at regular cost and use a ticket for 2nd item. Total amount of money spent = (2 + (4 / 2)) = 4 ≤ M. Total Profit obtained is = 20 + 17 = 37Input: N = 3, cost[] = {4, 4, 3}, profit[] = {12, 14, 7}, K = 2, M = 5
Output: 26
Explanation: The most optimal case is when we take the 1st stock using the 1st ticket and the 2nd item using the 2nd ticket. Total amount of money spent = ((4 / 2) + (4 / 2)) = 4 ≤ M. Total Profit obtained is = 12 +14 = 26
Naive Approach: Implement the idea below to solve the problem:
It is always beneficial to use the maximum number of tickets because it will reduce the price of the stock. For each item there are 3 choices:
- Don’t consider the current stock.
- Take the current but don’t use the ticket.
- Take the current and use the ticket.
Steps were taken to solve the problem:
- Initialise the integer variable Ans for storing maximum profit earned.
- To consider all subsets of items, for a given element we have 3 choices:
- Don’t take the current Stock, then the current amount left will be M, Ans remain the same.
- If possible(M ≥ cost[i]), take the current stock and add its profit value to the Ans then the current money left will be M – cost[i].
- If the ticket is used, add its profit value to the Ans, then the current money left will be M – cost[i]/2.
- Return maximum Ans of the above three possible cases.
Below is the code implementation of the above approach.
C++
// C++ code for the above approach #include <bits/stdc++.h> using namespace std; // Function to calculate Maximum Profit int maxProfit( int i, int N, int cost[], int profit[], int K, int M) { if (i == N) { return 0; } // Don't take the current stock int ans1 = maxProfit(i + 1, N, cost, profit, K, M); int ans2 = INT_MIN; int ans3 = INT_MIN; // If current stock can be taken // take it if (M >= cost[i]) { ans2 = profit[i] + maxProfit(i + 1, N, cost, profit, K, M - cost[i]); } // If current stock can be taken // with ticket take it if (K > 0) { int newcost = cost[i] / 2; if (M >= newcost) { ans3 = profit[i] + maxProfit(i + 1, N, cost, profit, K - 1, M - newcost); } } // Returning maximum profit earned return max(ans1, max(ans2, ans3)); } // Drivers code int main() { int cost[] = { 2, 4, 5 }; int profit[] = { 20, 17, 15 }; int N = sizeof (cost) / sizeof (cost[0]); int K = 1, M = 4; // Function call cout << maxProfit(0, N, cost, profit, K, M); return 0; } |
Java
// Java code for the above approach import java.io.*; class GFG { // Function to calculate Maximum profit static int maxProfit( int i, int N, int [] cost, int [] profit, int K, int M) { if (i == N) { return 0 ; } // Don't take the current stock int ans1 = maxProfit(i + 1 , N, cost, profit, K, M); int ans2 = Integer.MIN_VALUE; int ans3 = Integer.MIN_VALUE; // If current stock can be taken take it if (M >= cost[i]) { ans2 = profit[i] + maxProfit(i + 1 , N, cost, profit, K, M - cost[i]); } // If current stock can be taken with ticket take it if (K > 0 ) { int newcost = cost[i] / 2 ; if (M >= newcost) { ans3 = profit[i] + maxProfit(i + 1 , N, cost, profit, K - 1 , M - newcost); } } // Returning maximum profit earned return Math.max(ans1, Math.max(ans2, ans3)); } public static void main(String[] args) { int [] cost = { 2 , 4 , 5 }; int [] profit = { 20 , 17 , 15 }; int N = cost.length; int K = 1 , M = 4 ; // Function call System.out.print( maxProfit( 0 , N, cost, profit, K, M)); } } // This code is contributed by lokesh. |
Python3
# Python code for the above approach import sys # Function to calculate Maximum Profit def maxProfit(i,N,cost,profit,K,M): if (i = = N): return 0 # Don't take the current stock ans1 = maxProfit(i + 1 ,N,cost,profit,K,M) ans2 = - 1 * sys.maxsize ans3 = - 1 * sys.maxsize # If current stock can be taken # take it if (M > = cost[i]): ans2 = profit[i] + maxProfit(i + 1 , N, cost, profit, K, M - cost[i]) # If current stock can be taken # with ticket take it if (K > 0 ): newcost = cost[i] / / 2 if (M > = newcost): ans3 = profit[i] + maxProfit(i + 1 , N, cost, profit, K - 1 , M - newcost) # Returning maximum profit earned return max (ans1, max (ans2, ans3)) # Driver code cost = [ 2 , 4 , 5 ] profit = [ 20 , 17 , 15 ] N = len (cost) K = 1 M = 4 # Function call print (maxProfit( 0 , N, cost, profit, K, M)) # This code is contributed by Pushpesh Raj. |
C#
// C# implementation using System; public class GFG { // Function to calculate Maximum Profit public static int maxProfit( int i, int N, int [] cost, int [] profit, int K, int M) { if (i == N) { return 0; } // Don't take the current stock int ans1 = maxProfit(i + 1, N, cost, profit, K, M); int ans2 = Int32.MinValue; int ans3 = Int32.MinValue; // If current stock can be taken // take it if (M >= cost[i]) { ans2 = profit[i] + maxProfit(i + 1, N, cost, profit, K, M - cost[i]); } // If current stock can be taken // with ticket take it if (K > 0) { int newcost = ( int )(cost[i] / 2); if (M >= newcost) { ans3 = profit[i] + maxProfit(i + 1, N, cost, profit, K - 1, M - newcost); } } // Returning maximum profit earned return Math.Max(ans1, Math.Max(ans2, ans3)); } static public void Main() { int [] cost = { 2, 4, 5 }; int [] profit = { 20, 17, 15 }; int N = cost.Length; int K = 1, M = 4; // Function call Console.WriteLine( maxProfit(0, N, cost, profit, K, M)); } } // This code is contributed by ksam24000. |
Javascript
// javascript code for the above approach // Function to calculate Maximum Profit function maxProfit(i, N, cost,profit, K, M) { if (i == N) { return 0; } // Don't take the current stock let ans1 = maxProfit(i + 1, N, cost, profit, K, M); let ans2 = Number.MIN_VALUE; let ans3 = Number.MIN_VALUE; // If current stock can be taken // take it if (M >= cost[i]) { ans2 = profit[i] + maxProfit(i + 1, N, cost, profit, K, M - cost[i]); } // If current stock can be taken // with ticket take it if (K > 0) { let newcost = cost[i] / 2; if (M >= newcost) { ans3 = profit[i] + maxProfit(i + 1, N, cost, profit, K - 1, M - newcost); } } // Returning maximum profit earned return Math.max(ans1, Math.max(ans2, ans3)); } // Drivers code let cost = [ 2, 4, 5 ]; let profit = [ 20, 17, 15 ]; let N = cost.length, K = 1, M = 4; // Function call console.log(maxProfit(0, N, cost, profit, K, M)); // This code is contributed by garg28harsh. |
37
Time Complexity = O(3N)
Auxiliary Space = O(1)
Efficient Approach using Dynamic Programming:
The above approach has overlapping subproblems as can be seem below. Say:
M = 5, N = 3, K = 2, Cost[] = {4, 4, 3}, Profit[]={ 12, 14, 7}
Let X(M, 0, K) represent the given state that M initial money and K tickets and at index 0:
- Left move – 1st case – Don’t take current element
- Down move – 2nd case – Take the current element
- Right move – 3rd case – Take the current element with Ticket.
The recursion tree for the test case
So we can use the concept of dynamic programming.
Follow the steps mentioned below to implement the idea:
- Initialize a 3D array (say dp[][][]) to store the value of each state as shown above.
- Now use the same recursion as the previous approach.
- To reduce the calculation, if a state which is already calculated is encountered, return the maximum profit for that state.
- The value stored at the state (M, 0, K) is the required answer.
Below is the implementation of the efficient approach.
C++
// C++ implementation of the code #include <bits/stdc++.h> using namespace std; // Initialize 3D dp int dp[1001][501][11]; // Function to calculate Maximum profit // earned int maxProfit( int i, int N, int cost[], int profit[], int K, int M) { if (i == N) { return 0; } // State of dp already calculated or not if (dp[M][i][K] != -1) { return dp[M][i][K]; } // Don't take the current stock int ans1 = maxProfit(i + 1, N, cost, profit, K, M); int ans2 = INT_MIN; int ans3 = INT_MIN; // if current stock can be taken take it if (M >= cost[i]) { ans2 = profit[i] + maxProfit(i + 1, N, cost, profit, K, M - cost[i]); } // if current stock can be taken with // ticket take it if (K > 0) { int newcost = cost[i] / 2; if (M >= newcost) { ans3 = profit[i] + maxProfit(i + 1, N, cost, profit, K - 1, M - newcost); } } // store the current dp state and return // the ans return dp[M][i][K] = max(ans1, max(ans2, ans3)); } int main() { // Number of stocks int N = 3; int cost[3] = { 2, 4, 5 }; int profit[3] = { 20, 17, 15 }; // Tickets to use int K = 1; // Current Money int M = 4; // Setting all values of dp array to -1 memset (dp, -1, sizeof (dp)); // Function call cout << maxProfit(0, N, cost, profit, K, M); return 0; } |
Java
// Java implementation of the code import java.util.*; public class GFG { // Initialize 3D dp static int dp[][][] = new int [ 1001 ][ 501 ][ 11 ]; // Function to calculate Maximum profit // earned public static int maxProfit( int i, int N, int cost[], int profit[], int K, int M) { if (i == N) { return 0 ; } // State of dp already calculated or not if (dp[M][i][K] != - 1 ) { return dp[M][i][K]; } // Don't take the current stock int ans1 = maxProfit(i + 1 , N, cost, profit, K, M); int ans2 = Integer.MIN_VALUE; int ans3 = Integer.MIN_VALUE; // if current stock can be taken take it if (M >= cost[i]) { ans2 = profit[i] + maxProfit(i + 1 , N, cost, profit, K, M - cost[i]); } // if current stock can be taken with // ticket take it if (K > 0 ) { int newcost = cost[i] / 2 ; if (M >= newcost) { ans3 = profit[i] + maxProfit(i + 1 , N, cost, profit, K - 1 , M - newcost); } } // store the current dp state and return // the ans return dp[M][i][K] = Math.max(ans1, Math.max(ans2, ans3)); } public static void main(String args[]) { // Number of stocks int N = 3 ; int cost[] = { 2 , 4 , 5 }; int profit[] = { 20 , 17 , 15 }; // Tickets to use int K = 1 ; // Current Money int M = 4 ; // Setting all values of dp array to -1 for ( int i = 0 ; i < 1001 ; i++) { for ( int j = 0 ; j < 501 ; j++) { for ( int k = 0 ; k < 11 ; k++) { dp[i][j][k] = - 1 ; } } } // Function call System.out.println( maxProfit( 0 , N, cost, profit, K, M)); } } // This code is contributed by Samim Hossain Mondal. |
Python3
# Python implementation of the code # Initialize 3D dp dp = [[[ - 1 for k in range ( 11 )] for j in range ( 501 )] for i in range ( 1001 )] # Function to calculate Maximum profit # earned def maxProfit(i, N, cost, profit, K, M): if i = = N: return 0 # State of dp already calculated or not if dp[M][i][K] ! = - 1 : return dp[M][i][K] # Don't take the current stock ans1 = maxProfit(i + 1 , N, cost, profit, K, M) ans2 = float ( '-inf' ) ans3 = float ( '-inf' ) # if current stock can be taken take it if M > = cost[i]: ans2 = profit[i] + maxProfit(i + 1 , N, cost, profit, K, M - cost[i]) # if current stock can be taken with # ticket take it if K > 0 : newcost = cost[i] / / 2 if M > = newcost: ans3 = profit[i] + maxProfit(i + 1 , N, cost, profit, K - 1 , M - newcost) # store the current dp state and return # the ans dp[M][i][K] = max (ans1, max (ans2, ans3)) return dp[M][i][K] # Number of stocks N = 3 cost = [ 2 , 4 , 5 ] profit = [ 20 , 17 , 15 ] # Tickets to use K = 1 # Current Money M = 4 # Function call print (maxProfit( 0 , N, cost, profit, K, M)) # This code is contributed by Harshad |
C#
// C# implementation of the code using System; using System.Collections; using System.Collections.Generic; public class GFG { // Initialize 3D dp static int [, , ] dp = new int [1001, 501, 11]; // Function to calculate Maximum profit // earned public static int maxProfit( int i, int N, int [] cost, int [] profit, int K, int M) { if (i == N) { return 0; } // State of dp already calculated or not if (dp[M, i, K] != -1) { return dp[M, i, K]; } // Don't take the current stock int ans1 = maxProfit(i + 1, N, cost, profit, K, M); int ans2 = Int32.MinValue; int ans3 = Int32.MinValue; // if current stock can be taken take it if (M >= cost[i]) { ans2 = profit[i] + maxProfit(i + 1, N, cost, profit, K, M - cost[i]); } // if current stock can be taken with // ticket take it if (K > 0) { int newcost = cost[i] / 2; if (M >= newcost) { ans3 = profit[i] + maxProfit(i + 1, N, cost, profit, K - 1, M - newcost); } } // store the current dp state and return // the ans return dp[M, i, K] = Math.Max(ans1, Math.Max(ans2, ans3)); } public static void Main( string [] args) { // Number of stocks int N = 3; int [] cost = { 2, 4, 5 }; int [] profit = { 20, 17, 15 }; // Tickets to use int K = 1; // Current Money int M = 4; // Setting all values of dp array to -1 for ( int i = 0; i < 1001; i++) { for ( int j = 0; j < 501; j++) { for ( int k = 0; k < 11; k++) { dp[i, j, k] = -1; } } } // Function call Console.WriteLine( maxProfit(0, N, cost, profit, K, M)); } } // This code is contributed by Karandeep1234 |
Javascript
// Javascript implementation of the code // Initialize 3D dp let dp = Array(1001).fill().map(e => Array(501).fill().map(e => Array(11).fill(-1).map(e => e))); // Function to calculate Maximum profit // earned function maxProfit(i, N, cost, profit, K, M) { if (i == N) { return 0; } // State of dp already calculated or not if (dp[M][i][K] != -1) { return dp[M][i][K]; } // Don't take the current stock let ans1 = maxProfit(i + 1, N, cost, profit, K, M); let ans2 = Number.MIN_SAFE_INTEGER; let ans3 = Number.MIN_SAFE_INTEGER; // if current stock can be taken take it if (M >= cost[i]) { ans2 = profit[i] + maxProfit(i + 1, N, cost, profit, K, M - cost[i]); } // if current stock can be taken with // ticket take it if (K > 0) { let newcost = Math.floor(cost[i] / 2); if (M >= newcost) { ans3 = profit[i] + maxProfit(i + 1, N, cost, profit, K - 1, M - newcost); } } // store the current dp state and return // the ans return dp[M][i][K] = Math.max(ans1, Math.max(ans2, ans3)); } // Number of stocks let N = 3; let cost = [ 2, 4, 5 ]; let profit = [ 20, 17, 15 ]; // Tickets to use let K = 1; // Current Money let M = 4; // Setting all values of dp array to -1 for (let i = 0; i < 1001; i++) { for (let j = 0; j < 501; j++) { for (let k = 0; k < 11; k++) { dp[i][j][k] = -1; } } } // Function call console.log(maxProfit(0, N, cost, profit, K, M)); // This code is contributed by Utkarsh |
37
Time Complexity: O(N*M*K)
Auxiliary Space: O(N*M*K)
Related articles:
- Introduction to Arrays – Data Structure and Algorithm Tutorials
- Introduction to Dynamic Programming – Data Structures and Algorithm Tutorials
Please Login to comment...