Open In App

Maximize profit by picking elements of different types with total weight K

Improve
Improve
Like Article
Like
Save
Share
Report

Given an array item[] representing type, weight, and profit of N items, the task is to maximize the profit by picking different types of elements (i.e., no two elements are of the same type) such that the total weight is at most pick atmost K.

Examples:

Input: item[] = [[1, 3, 13], [5, 1, 10], [2, 2, 1], [1, 4, 9], [4, 5, 11], [1, 5, 9] ], K = 6
Output: 24
Explanation: The maximum value obtained is 24. 
You can take items of type1 with a profit of 13 and type5 with a profit of 10 and type2 with a profit of 1. 
Hence the value = 13 + 10 + 1 = 24

Input: item[] = [[1, 3, 13], [5, 1, 10], [2, 2, 1], [1, 4, 9], [4, 5, 11], [1, 5, 9] ], K = 9
Output: 34
Explanation: The maximum value obtained is 34. 
You can take items of type1 with a profit of 13 and of type5 with a profit of 10 and type4 with a profit of 11. 
Hence the value = 13 + 10 + 11 = 34

Approach: The problem can be solved using recursion based on the following idea:

For each element of the item, we are having two choices whether to take that particular item or not.

  • Case 1 – Pick Case: When the weight of the item present at item[index][1] is less than or equal to K as well as the item of that type has not been brought so far, the profit of that item will get add up in our total value and the total weight K will get reduced by the weight of the current item and type of that item will get add up to the set saying this type item had been taken.
  • Case 2 – Not Pick Case: When the item present at item[index] does not get included in the final result, no profit i.e. 0 will get added up in our total value.

You can include items if and only if the current item weight is less than or equal to the total weight available and an item of that type has not been brought so far.

Follow the steps mentioned below to implement the idea:

  • Create a recursive function.
  • For each call, there are two choices for the item as mentioned above.
  • Calculate the value of all possible cases as mentioned above.
  • The maximum among them is the required answer.

Below is the implementation of the above approach:

C++




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function for calculating maximum profit.
int solve(int index, vector<vector<int> >& item,
          set<int> st, int K)
{
    if (K == 0)
        return 0;
    if (index == 0) {
        if (st.find(item[index][0]) == st.end()
            && item[index][1] <= K) {
            return item[index][2];
        }
        else
            return INT_MIN;
    }
 
    // Not picking case
    int not_pick = 0 + solve(index - 1, item, st, K);
    int pick = INT_MIN;
 
    // Picking case
    if (item[index][1] <= K
        && st.find(item[index][0]) == st.end()) {
        st.insert(item[index][0]);
 
        // Inserting into set indicating
        // this type of item has been taken
        pick = item[index][2]
               + solve(index - 1, item, st,
                       K - item[index][1]);
    }
 
    // Returning the maximum out of both cases.
    return max(pick, not_pick);
}
 
// Driver code
int main()
{
    vector<vector<int> > item
        = { { 1, 3, 13 }, { 5, 1, 10 }, { 2, 2, 1 }, { 1, 4, 9 }, { 4, 5, 11 }, { 1, 5, 9 } };
 
    int N = item.size(), K = 6;
 
    // defining set for having type records.
    set<int> st;
 
    // Function call
    cout << "Maximum value obtained: "
         << solve(N - 1, item, st, K);
 
    return 0;
}


Java




// Java code to implement the approach
import java.io.*;
import java.util.*;
 
class GFG {
 
  // Function for calculating maximum profit.
  static int solve(int index, int[][] item,
                   Set<Integer> st, int K)
  {
    if (K == 0)
      return 0;
    if (index == 0) {
      if (!st.contains(item[index][0])
          && item[index][1] <= K) {
        return item[index][2];
      }
      else
        return Integer.MIN_VALUE;
    }
 
    // Not picking case
    int notPick = 0 + solve(index - 1, item, st, K);
    int pick = Integer.MIN_VALUE;
 
    // Picking case
    if (item[index][1] <= K
        && !st.contains(item[index][0])) {
      st.add(item[index][0]);
 
      // Inserting into set indicating
      // this type of item has been taken
      pick = item[index][2]
        + solve(index - 1, item, st,
                K - item[index][1]);
    }
 
    // Returning the maximum out of both cases.
    return Math.max(pick, notPick);
  }
 
  // Driver code
  public static void main(String[] args)
  {
    int[][] item
      = { { 1, 3, 13 }, { 5, 1, 10 }, { 2, 2, 1 },
         { 1, 4, 9 },  { 4, 5, 11 }, { 1, 5, 9 } };
    int N = item.length, K = 6;
 
    // defining set for having type records.
    Set<Integer> st = new HashSet<>();
 
    // Function call
    System.out.println("Maximum value obtained: "
                       + (solve(N - 1, item, st, K) + 1));
  }
}
 
// This code is contributed by lokesh.


Python3




# Python code to implement the approach
 
from typing import List, Tuple
 
def solve(index: int, item: List[Tuple[int, int, int]], st: set, K: int) -> int:
    if K == 0:
        return 0
    if index == 0:
        if item[index][0] not in st and item[index][1] <= K:
            return item[index][2]
        else:
            return float("-inf")
 
    # Not picking case
    not_pick = 0 + solve(index - 1, item, st, K)
    pick = float("-inf")
 
    # Picking case
    if item[index][1] <= K and item[index][0] not in st:
        st.add(item[index][0])
        pick = item[index][2] + solve(index - 1, item, st, K - item[index][1])
        st.remove(item[index][0])
 
    # Returning the maximum out of both cases.
    return max(pick, not_pick)
 
 
# Driver code
if __name__ == "__main__":
    item = [ (1, 3, 13), (5, 1, 10), (2, 2, 1), (1, 4, 9), (4, 5, 11), (1, 5, 9) ]
 
    N = len(item)
    K = 6
 
    # defining set for having type records.
    st = set()
 
    # Function call
    print("Maximum value obtained: ", solve(N - 1, item, st, K))
 
# This code is contributed by Vikram_Shirsat


C#




// C# code to implement the approach
using System;
using System.Collections.Generic;
 
public class GFG
{
  // Function for calculating maximum profit.
  static int Solve(int index, List<List<int>> item,
                   HashSet<int> st, int K)
  {
    if (K == 0)
      return 0;
    if (index == 0)
    {
      if (st.Contains(item[index][0]) == false
          && item[index][1] <= K)
      {
        return item[index][2];
      }
      else
        return Int32.MinValue;
    }
 
    // Not picking case
    int not_pick = 0 + Solve(index - 1, item, st, K);
    int pick = Int32.MinValue;
 
    // Picking case
    if (item[index][1] <= K
        && st.Contains(item[index][0]) == false)
    {
      st.Add(item[index][0]);
 
      // Inserting into set indicating
      // this type of item has been taken
      pick = item[index][2]
        + Solve(index - 1, item, st,
                K - item[index][1]);
    }
 
    // Returning the maximum out of both cases.
    return Math.Max(pick, not_pick);
  }
 
  // Driver code
  public static void Main()
  {
    List<List<int>> item
      = new List<List<int>>() {
      new List<int> { 1, 3, 13 },
      new List<int> { 5, 1, 10 },
      new List<int> { 2, 2, 1 },
      new List<int> { 1, 4, 9 },
      new List<int> { 4, 5, 11 },
      new List<int> { 1, 5, 9 } };
 
    int N = item.Count, K = 6;
 
    // defining set for having type records.
    HashSet<int> st = new HashSet<int>();
 
    // Function call
    Console.Write("Maximum value obtained: "
                  + (Solve(N - 1, item, st, K)+1));
  }
}
 
// This code is contributed by ishankhandelwals.


Javascript




// JS code to implement the approach
 
const solve = (index, item, st, K) => {
  if (K === 0) return 0;
  if (index === 0) {
      if (!st.has(item[index][0]) && item[index][1] <= K) {
          return item[index][2];
      } else {
          return Number.MIN_VALUE;
      }
  }
 
  // Not picking case
  let not_pick = 0 + solve(index - 1, item, st, K);
  let pick = Number.MIN_VALUE;
 
  // Picking case
  if (item[index][1] <= K && !st.has(item[index][0])) {
      st.add(item[index][0]);
 
      // Inserting into set indicating
      // this type of item has been taken
      pick = item[index][2] + solve(index - 1, item, st, K - item[index][1]);
  }
 
  // Returning the maximum out of both cases.
  return Math.max(pick, not_pick);
}
 
// Driver code
let item = [[1, 3, 13], [5, 1, 10], [2, 2, 1], [1, 4, 9], [4, 5, 11], [1, 5, 9]];
let N = item.length, K = 6;
 
// defining set for having type records.
let st = new Set();
 
// Function call
console.log(`Maximum value obtained: ${solve(N - 1, item, st, K)+1}`);
 
// This code is contributed by ishankhandelwals.


Output

Maximum value obtained: 24

Time Complexity: O(2N)
Auxiliary Space: O(N)

Another Approach:

  • Sort the items array in decreasing order of profits.
  • Initialize a set to keep track of the types of items picked so far.
  • Initialize a variable to keep track of the total weight picked so far.
    Initialize a variable to keep track of the total profit picked so far.
  • Traverse the sorted items array from the beginning.
  • If the type of the current item is not already in the set, and picking this item will not exceed the weight limit, then add the type of the current item to the set, add the weight and profit of the current item to their respective variables, and continue to the next item.
  • If the type of the current item is already in the set or picking this item will exceed the weight limit, then continue to the next item.
  • Return the total profit picked so far.

C++




#include <bits/stdc++.h>
using namespace std;
 
bool compare(vector<int>& a, vector<int>& b) {
    return a[2] > b[2]; // Sort in decreasing order of profit
}
 
int maximizeProfit(vector<vector<int>>& items, int k) {
    sort(items.begin(), items.end(), compare);
    set<int> types;
    int weight = 0, profit = 0;
    for (auto item : items) {
        if (types.find(item[0]) == types.end() && weight + item[1] <= k) {
            types.insert(item[0]);
            weight += item[1];
            profit += item[2];
        }
    }
    return profit;
}
 
int main() {
    vector<vector<int>> items = {{1, 3, 13}, {5, 1, 10}, {2, 2, 1}, {1, 4, 9}, {4, 5, 11}, {1, 5, 9}};
    int k = 6;
    cout << maximizeProfit(items, k) << endl; // Output: 24
 
    return 0;
}


Java




import java.util.*;
 
class Main {
    public static int compare(List<Integer> a, List<Integer> b) {
        return b.get(2) - a.get(2); // Sort in decreasing order of profit
    }
 
    public static int maximizeProfit(List<List<Integer>> items, int k) {
        Collections.sort(items, Main::compare);
        Set<Integer> types = new HashSet<>();
        int weight = 0, profit = 0;
        for (List<Integer> item : items) {
            if (!types.contains(item.get(0)) && weight + item.get(1) <= k) {
                types.add(item.get(0));
                weight += item.get(1);
                profit += item.get(2);
            }
        }
        return profit;
    }
 
    public static void main(String[] args) {
        List<List<Integer>> items = Arrays.asList(
            Arrays.asList(1, 3, 13),
            Arrays.asList(5, 1, 10),
            Arrays.asList(2, 2, 1),
            Arrays.asList(1, 4, 9),
            Arrays.asList(4, 5, 11),
            Arrays.asList(1, 5, 9)
        );
        int k = 6;
        System.out.println(maximizeProfit(items, k)); // Output: 24
    }
}


Python3




# Python code addition
 
def compare(a, b):
    return a[2] > b[2# Sort in decreasing order of profit
 
def maximizeProfit(items, k):
    items.sort(key=lambda x: x[2], reverse=True)
    types = set()
    weight = 0
    profit = 0
    for item in items:
        if item[0] not in types and weight + item[1] <= k:
            types.add(item[0])
            weight += item[1]
            profit += item[2]
    return profit
 
items = [
    [1, 3, 13],
    [5, 1, 10],
    [2, 2, 1],
    [1, 4, 9],
    [4, 5, 11],
    [1, 5, 9]
]
k = 6
print(maximizeProfit(items, k))
 
# The code is contributed by Nidhi goel.


C#




using System;
using System.Collections.Generic;
using System.Linq;
 
public class Program
{
    public static int MaximizeProfit(List<int[]> items, int k)
    {
        items.Sort((a, b) => b[2].CompareTo(a[2])); // Sort in decreasing order of profit
 
        HashSet<int> types = new HashSet<int>();
        int weight = 0;
        int profit = 0;
 
        foreach (var item in items)
        {
            if (!types.Contains(item[0]) && weight + item[1] <= k)
            {
                types.Add(item[0]);
                weight += item[1];
                profit += item[2];
            }
        }
 
        return profit;
    }
 
    public static void Main(string[] args)
    {
        List<int[]> items = new List<int[]>
        {
            new int[] { 1, 3, 13 },
            new int[] { 5, 1, 10 },
            new int[] { 2, 2, 1 },
            new int[] { 1, 4, 9 },
            new int[] { 4, 5, 11 },
            new int[] { 1, 5, 9 }
        };
        int k = 6;
        Console.WriteLine(MaximizeProfit(items, k));
    }
}


Javascript




function compare(a, b) {
    return a[2] > b[2]; // Sort in decreasing order of profit
}
 
function maximizeProfit(items, k) {
    items.sort(compare);
    const types = new Set();
    let weight = 0,
        profit = 0;
    for (const item of items) {
        if (!types.has(item[0]) && weight + item[1] <= k) {
            types.add(item[0]);
            weight += item[1];
            profit += item[2];
        }
    }
    return profit;
}
 
const items = [
    [1, 3, 13],
    [5, 1, 10],
    [2, 2, 1],
    [1, 4, 9],
    [4, 5, 11],
    [1, 5, 9]
];
const k = 6;
console.log(maximizeProfit(items, k));
// This code is contributed by user_dtewbxkn77n


Output

24

Time Complexity: O(N log N)

Auxiliary space: O(N)

Related Articles:



Last Updated : 07 Jul, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads