Open In App

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

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:

Below is the implementation of the above approach:




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




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




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




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




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




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




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));
    }
}




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:


Article Tags :