Open In App

Theft at World Bank

Last Updated : 31 Jan, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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:

  • Initialize a vector of pairs say V to store the pairs formed by taking array elements from the array B[] as the first element and the array elements from array B[] as the second element present at the same index.
  • Iterate over the range [0, N] and if A[i] is not a, perfect square then push the pair {B[i], A[i]} into the vector V.
  • Sort the vector V in descending order by a custom comparator by the ratios of the pairs.
  • Initialize a variable say profit as 0 to store the maximum profit.
  • Traverse the vector V and perform the following steps in each iteration:
    • If the second element of the current pair is less than or equal to W, then increment profit by the first element of the pair, i.e taking the whole block of gold and then decrease W by the second element of the current pair.
    • Otherwise, take an amount equal to the ratio of W and the second element of the current pair and store it in a variable P. Then increment profit by P*first element of the current pair and then break.
  • Finally, after completing the above steps, print the value obtained in profit as the answer.

Below is the implementation of the above approach:

C++




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




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




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




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


Javascript




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

 



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads