Open In App

Theft at World Bank

Given a sac of capacity W, and two arrays A[] and B[] of length N, where A[i] represents the weight of an ith block of gold and B[i] represents the profit gained by taking the ith block of gold, the task is to find the maximum profit gained by taking some part or whole of a gold block with not perfect square weight, not exceeding the sac capacity.

Examples:



Input: A[]= {4, 5, 7}, B[] = {8, 5, 4), W = 10
Output: 7.857
Explanation:
One way to obtain the maximum profit is:

  1. Take the whole second block, getting a profit of 5 and reducing the capacity to 5.
  2. Take a fraction of 5/7 of the third block, getting a profit of (5/7)*4 = 2.857 and reducing the capacity to 0.

Thus, the maximum obtained profit is equal to (5+2.857 = 7.857), which is the maximum possible.

Input: A[]= {2, 5, 3}, B[] = {7, 6, 9), W = 8
Output: 19.600

Approach: The given problem can be solved using a greedy algorithm known as fractional Knapsack. Follow the steps below to solve the problem:



Below is the implementation of the above approach:




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Custom comparator
bool comp(pair<long long, long long> p1,
          pair<long long, long long> p2)
{
    long double a = p1.first, b = p1.second;
    long double c = p2.first, d = p2.second;
    long double val1 = 0, val2 = 0;
    val1 = a / b;
    val2 = c / d;
 
    return val1 > val2;
}
 
// Function to find the maximum profit
long double maximumProfit(int A[], int B[], int N,
                          long long W)
{
    // Stores the pairs of elements
    // of B and A at the same index
    vector<pair<long long, long long> > V;
 
    // Iterate over the range
    //[0, N]
    for (int i = 0; i < N; i++) {
 
        long long temp = sqrt(A[i]);
 
        // If current integer is
        // perfect square
        if (temp * temp == A[i])
            continue;
 
        // Push the pair of B[i]
        // and A[i] in vector V
        V.push_back({ B[i], A[i] });
    }
 
    // Sorts the vector using
    // the custom comparator
    sort(V.begin(), V.end(), comp);
 
    // Stores the maximum profit
    long double profit = 0.00;
 
    // Traverse the vector V
    for (int i = 0; i < V.size(); i++) {
        // If V[i].second is less
        // than W
        if (V[i].second <= W) {
            // Increment profit by
            // V[i].first
            profit += V[i].first;
 
            // Decrement V[i].second
            // from W
            W -= V[i].second;
        }
        // Otherwise
        else {
            // Update profit
            profit += V[i].first
                      * ((long double)W / (long double)V[i].second);
            break;
        }
    }
    // Return the value of profit
    return profit;
}
// Driver Code
int main()
{
 
    int N = 3;
    long long W = 10;
    int A[] = { 4, 5, 7 };
    int B[] = { 8, 5, 4 };
 
    cout << maximumProfit(A, B, N, W) << endl;
 
    return 0;
}




// Java program for the above approach
import java.io.*;
import java.util.*;
 
class Pair {
  double first, second;
  Pair(double first, double second)
  {
    this.first = first;
    this.second = second;
  }
}
 
class GFG {
 
  static class ComparePairs implements Comparator<Pair> {
    public int compare(Pair p1, Pair p2)
    {
      double a = p1.first, b = p1.second;
      double c = p2.first, d = p2.second;
      double val1 = 0, val2 = 0;
      val1 = a / b;
      val2 = c / d;
      if (val1 > val2) {
        return -1;
      }
      else if (val1 < val2) {
        return 1;
      }
      else {
        return 0;
      }
    }
  }
 
  static double maximumProfit(int[] A, int[] B, int N,
                              double W)
  {
    List<Pair> V = new ArrayList<Pair>();
    for (int i = 0; i < N; i++) {
      double temp = (double)Math.sqrt(A[i]);
      if (temp * temp == A[i]) {
        continue;
      }
      V.add(new Pair(B[i], A[i]));
    }
    V.sort(new ComparePairs());
    double profit = 0.00;
    for (int i = 0; i < V.size(); i++) {
      if (V.get(i).second <= W) {
        profit += V.get(i).first;
        W -= V.get(i).second;
      }
      else {
        profit += V.get(i).first
          * ((double)W
             / (double)V.get(i).second);
        break;
      }
    }
    return profit;
  }
 
  public static void main(String[] args)
  {
    int N = 3;
    double W = 10;
    int[] A = { 4, 5, 7 };
    int[] B = { 8, 5, 4 };
    System.out.println(String.format(
      "%.5f", maximumProfit(A, B, N, W)));
  }
}
 
// This code is contributed by lokeshmvs21.




# Python3 program for the above approach
import math
from functools import cmp_to_key
 
# Custom comparator
def comparator(p1, p2):
     
    a = p1[0]
    b = p1[1]
    c = p2[0]
    d = p2[1]
    val1 = a / b
    val2 = c / d
    return val1 > val2
 
# Function to find the maximum profit
def maximumProfit(A, B, N, W):
   
    # Stores the pairs of elements
    # of B and A at the same index
    V = []
 
    # Iterate over the range [0,N]
    for i in range(0, N):
       
        temp = int(math.sqrt(A[i]))
         
        # If current integer is
        # perfect square
        if temp * temp == A[i]:
            continue
         
        # Push the pair of B[i]
        # and A[i] in vector V
        V.append([B[i], A[i]])
         
    # Sort the vector using
    # the custom comparator
    V = sorted(V, key = cmp_to_key(comparator))
     
    # Stores the maximum profit
    profit = 0.00
     
    # Traverse the vector V
    k = len(V)
    for i in range(k):
       
        # If V[i][1] is less
        # than W
        if V[i][1] <= W:
             
            # Increment profit by
            # V[i][0]
            profit += V[i][0]
             
            # Decrement V[i][0]
            # from W
            W -= V[i][1]
             
        # Otherwise
        else:
             
            # Update profit
            profit += (V[i][0] * W) / V[i][1]
            break
             
    # Return the value of profit
    return profit
 
# Driver Code
if __name__ == '__main__':
   
    N = 3
    W = 10
    A = [ 4, 5, 7 ]
    B = [ 8, 5, 4 ]
     
    print(round(maximumProfit(A, B, N, W), 5))
     
# This code is contributed by MuskanKalra1




// C# code for the above approach
using System;
using System.Linq;
using System.Collections.Generic;
 
class GFG
{
   
  // Custom comparator
  public class comp : IComparer<Tuple<long, long>>
  {
    public int Compare(Tuple<long, long> p1, Tuple<long, long> p2)
    {
      double a = p1.Item1, b = p1.Item2;
      double c = p2.Item1, d = p2.Item2;
      double val1 = 0, val2 = 0;
      val1 = a / b;
      val2 = c / d;
 
      return (val1 > val2) ? 1 : -1;
    }
  }
 
  // Function to find the maximum profit
  public static double maximumProfit(int[] A, int[] B, int N, long W)
  {
    // Stores the pairs of elements
    // of B and A at the same index
    List<Tuple<long, long>> V = new List<Tuple<long, long>>();
 
    // Iterate over the range
    //[0, N]
    for (int i = 0; i < N; i++)
    {
      long temp = (long)Math.Sqrt(A[i]);
 
      // If current integer is
      // perfect square
      if (temp * temp == A[i])
        continue;
 
      // Push the pair of B[i]
      // and A[i] in vector V
      V.Add(new Tuple<long, long>((long)B[i], (long)A[i]));
    }
 
    // Sorts the vector using
    // the custom comparator
    V.Sort(new comp());
 
    // Stores the maximum profit
    double profit = 0.00;
 
    // Traverse the vector V
    for (int i = 0; i < V.Count; i++)
    {
      // If V[i].second is less
      // than W
      if (V[i].Item2 <= W)
      {
        // Increment profit by
        // V[i].first
        profit += V[i].Item1;
 
        // Decrement V[i].second
        // from W
        W -= V[i].Item2;
      }
      // Otherwise
      else
      {
        // Update profit
        profit += V[i].Item1 * (W / (double)V[i].Item2);
        break;
      }
    }
    // Return the value of profit
    return profit;
  }
 
  // Driver Code
  public static void Main(string[] args)
  {
 
    int N = 3;
    long W = 10;
    int[] A = { 4, 5, 7 };
    int[] B = { 8, 5, 4 };
 
    Console.WriteLine(maximumProfit(A, B, N, W));
  }
}
 
// This code is contributed by lokeshpotta20.




<script>
 
// JavaScript program for the above approach
 
 
// Custom comparator
function comp(p1, p2) {
    let a = p1[0], b = p1[1];
    let c = p2[0], d = p2[1];
    let val1 = 0, val2 = 0;
    val1 = Math.floor(a / b);
    val2 = Math.floor(c / d);
 
    return val1 > val2;
}
 
// Function to find the maximum profit
function maximumProfit(A, B, N, W) {
    // Stores the pairs of elements
    // of B and A at the same index
    let V = [];
 
    // Iterate over the range
    //[0, N]
    for (let i = 0; i < N; i++) {
 
        let temp = Math.sqrt(A[i]);
 
        // If current integer is
        // perfect square
        if (temp * temp == A[i])
            continue;
 
        // Push the pair of B[i]
        // and A[i] in vector V
        V.push([B[i], A[i]]);
    }
 
    // Sorts the vector using
    // the custom comparator
    V.sort(comp);
 
    // Stores the maximum profit
    let profit = 0.00;
 
    // Traverse the vector V
    for (let i = 0; i < V.length; i++) {
        // If V[i][1] is less
        // than W
        if (V[i][1] <= W) {
            // Increment profit by
            // V[i][0]
            profit += V[i][0];
 
            // Decrement V[i][1]
            // from W
            W -= V[i][1];
        }
        // Otherwise
        else {
            // Update profit
            profit += V[i][0]
                * (W / V[i][1]);
            break;
        }
    }
    // Return the value of profit
    return profit.toFixed(5);
}
// Driver Code
 
 
let N = 3;
let W = 10;
let A = [4, 5, 7];
let B = [8, 5, 4];
 
document.write(maximumProfit(A, B, N, W) + "<br>");
 
</script>

Output
7.85714

Time Complexity: O(N * log(N)) 
Auxiliary Space: O(N)

 


Article Tags :