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:
- Take the whole second block, getting a profit of 5 and reducing the capacity to 5.
- 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++ 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> |
7.85714
Time Complexity: O(N * log(N))
Auxiliary Space: O(N)