Given n gold boxes, where the i-th box contains a[i] plates and each plate in that box contains b[i] gold coins. A thief can carry at most t plates in total. He may take any number of plates from a box, but cannot take more plates than are available in that box. Return the maximum number of gold coins the thief can steal.
Examples:
Input: t = 3, a[] = [1, 2, 3], b[] = [3, 2, 1]
Output: 7
Explanation: The thief takes 1 plate from the first box and 2 plates from the second box.Total gold coins stolen = (1 × 3) + (2 × 2) = 7.
Input: t = 0, a[] = [1, 3, 2], b[] = [2, 3, 1]
Output: 0
Explanation: The thief cannot carry any plates, so he steals 0 gold coins.
Table of Content
[Naive Approach] Try Every Plate One by One - O(n × t) Time and O(n) Space
The idea is to repeatedly pick one plate at a time from the box that currently has the maximum coins per plate among all boxes with plates remaining.
For every plate the thief can carry, scan all boxes to find the best available box, take one plate from it, and reduce its remaining plate count. Continue this process until the carrying capacity is exhausted or no plates are left.
#include <iostream>
#include <vector>
using namespace std;
int maxCoins(int t, vector<int> &a, vector<int> &b)
{
int n = a.size();
// Store the remaining plates in each box
vector<int> remaining = a;
int ans = 0;
// Pick one plate at a time
while (t--)
{
int idx = -1;
// Find the box with the maximum coins per plate
for (int i = 0; i < n; i++)
{
if (remaining[i] > 0)
{
if (idx == -1 || b[i] > b[idx])
idx = i;
}
}
// No plates left in any box
if (idx == -1)
break;
ans += b[idx];
remaining[idx]--;
}
return ans;
}
int main()
{
int t = 3;
vector<int> a = {1, 2, 3};
vector<int> b = {3, 2, 1};
cout << maxCoins(t, a, b);
return 0;
}
import java.util.Arrays;
public class GFG {
public static int maxCoins(int t, int[] a, int[] b)
{
int n = a.length;
// Store the remaining plates in each box
int[] remaining = a.clone();
int ans = 0;
// Pick one plate at a time
while (t-- > 0) {
int idx = -1;
// Find the box with the maximum coins per plate
for (int i = 0; i < n; i++) {
if (remaining[i] > 0) {
if (idx == -1 || b[i] > b[idx])
idx = i;
}
}
// No plates left in any box
if (idx == -1)
break;
ans += b[idx];
remaining[idx]--;
}
return ans;
}
public static void main(String[] args)
{
int t = 3;
int[] a = { 1, 2, 3 };
int[] b = { 3, 2, 1 };
System.out.println(maxCoins(t, a, b));
}
}
def maxCoins(t, a, b):
n = len(a)
# Store the remaining plates in each box
remaining = a.copy()
ans = 0
# Pick one plate at a time
while t > 0:
t -= 1
idx = -1
# Find the box with the maximum coins per plate
for i in range(n):
if remaining[i] > 0:
if idx == -1 or b[i] > b[idx]:
idx = i
# No plates left in any box
if idx == -1:
break
ans += b[idx]
remaining[idx] -= 1
return ans
if __name__ == '__main__':
t = 3
a = [1, 2, 3]
b = [3, 2, 1]
print(maxCoins(t, a, b))
using System;
using System.Linq;
public class GFG {
public static int maxCoins(int t, int[] a, int[] b)
{
int n = a.Length;
// Store the remaining plates in each box
int[] remaining = (int[])a.Clone();
int ans = 0;
// Pick one plate at a time
while (t-- > 0) {
int idx = -1;
// Find the box with the maximum coins per plate
for (int i = 0; i < n; i++) {
if (remaining[i] > 0) {
if (idx == -1 || b[i] > b[idx])
idx = i;
}
}
// No plates left in any box
if (idx == -1)
break;
ans += b[idx];
remaining[idx]--;
}
return ans;
}
public static void Main()
{
int t = 3;
int[] a = { 1, 2, 3 };
int[] b = { 3, 2, 1 };
Console.WriteLine(maxCoins(t, a, b));
}
}
function maxCoins(t, a, b)
{
let n = a.length;
// Store the remaining plates in each box
let remaining = [...a ];
let ans = 0;
// Pick one plate at a time
while (t-- > 0) {
let idx = -1;
// Find the box with the maximum coins per plate
for (let i = 0; i < n; i++) {
if (remaining[i] > 0) {
if (idx == -1 || b[i] > b[idx])
idx = i;
}
}
// No plates left in any box
if (idx == -1)
break;
ans += b[idx];
remaining[idx]--;
}
return ans;
}
// Driver Code
let t = 3;
let a = [ 1, 2, 3 ];
let b = [ 3, 2, 1 ];
console.log(maxCoins(t, a, b));
Output
7
[Expected Approach] Greedy with Sorting - O(n log n) Time and O(n) Space
The idea is to always take plates from the box having the maximum coins per plate.
Since every plate in a box contains the same number of coins, it is always optimal to take as many plates as possible from boxes with higher coins per plate before considering boxes with lower coins per plate.
- Store each box as a pair of (coins per plate, number of plates).
- Sort these pairs in decreasing order of coins per plate, and greedily take the maximum possible plates from each box until the carrying capacity is exhausted.
Let us understand with an example:
Input: t = 3, a[] = [1, 2, 3], b[] = [3, 2, 1]
- Store each box as (coins per plate, number of plates): (3, 1), (2, 2), (1, 3).
- Sort the boxes in decreasing order of coins per plate. The order remains (3, 1), (2, 2), (1, 3).
- Take 1 plate from the first box, collect 3 coins, and reduce the remaining capacity from 3 to 2.
- Take 2 plates from the second box, collect 4 coins, and reduce the remaining capacity from 2 to 0.
- The carrying capacity is exhausted, so the maximum gold coins stolen are 3 + 4 = 7.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int maxCoins(int t, vector<int> &a, vector<int> &b)
{
int n = a.size();
vector<pair<int, int>> boxes;
// Store (coins per plate, number of plates) for each box
for (int i = 0; i < n; i++)
{
boxes.push_back({b[i], a[i]});
}
// Sort boxes in decreasing order of coins per plate
sort(boxes.begin(), boxes.end(), greater<pair<int, int>>());
int res = 0;
// Take plates greedily from boxes with maximum coins per plate
for (int i = 0; i < n && t > 0; i++)
{
int take = min(t, boxes[i].second);
res += take * boxes[i].first;
t -= take;
}
return res;
}
int main()
{
int t = 3;
vector<int> a = {1, 2, 3};
vector<int> b = {3, 2, 1};
cout << maxCoins(t, a, b);
return 0;
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class GFG {
static int maxCoins(int t, int[] a, int[] b) {
int n = a.length;
List<Pair> boxes = new ArrayList<>();
// Store (coins per plate, number of plates) for each box
for (int i = 0; i < n; i++) {
boxes.add(new Pair(b[i], a[i]));
}
// Sort boxes in decreasing order of coins per plate
Collections.sort(boxes, (p1, p2) -> p2.first - p1.first);
int res = 0;
// Take plates greedily from boxes with maximum coins per plate
for (int i = 0; i < n && t > 0; i++) {
int take = Math.min(t, boxes.get(i).second);
res += take * boxes.get(i).first;
t -= take;
}
return res;
}
public static void main(String[] args) {
int t = 3;
int[] a = {1, 2, 3};
int[] b = {3, 2, 1};
System.out.println(maxCoins(t, a, b));
}
static class Pair {
int first, second;
Pair(int first, int second) {
this.first = first;
this.second = second;
}
}
}
def maxCoins(t, a, b):
n = len(a)
boxes = []
# Store (coins per plate, number of plates) for each box
for i in range(n):
boxes.append((b[i], a[i]))
# Sort boxes in decreasing order of coins per plate
boxes.sort(key=lambda x: x[0], reverse=True)
res = 0
# Take plates greedily from boxes with maximum coins per plate
for i in range(n):
if t <= 0:
break
take = min(t, boxes[i][1])
res += take * boxes[i][0]
t -= take
return res
if __name__ == '__main__':
t = 3
a = [1, 2, 3]
b = [3, 2, 1]
print(maxCoins(t, a, b))
using System;
using System.Collections.Generic;
class GFG
{
public int maxCoins(int t, int[] a, int[] b)
{
int n = a.Length;
var boxes = new List<(int coins, int plates)>();
// Store (coins per plate, number of plates) for each box.
for (int i = 0; i < n; i++)
boxes.Add((b[i], a[i]));
// Sort boxes in decreasing order of coins per plate.
boxes.Sort((x, y) => y.coins.CompareTo(x.coins));
int res = 0;
// Take plates greedily from boxes with maximum coins per plate.
foreach (var box in boxes)
{
if (t == 0)
break;
int take = Math.Min(t, box.plates);
res += take * box.coins;
t -= take;
}
return res;
}
static void Main()
{
int t = 3;
int[] a = { 1, 2, 3 };
int[] b = { 3, 2, 1 };
GFG obj = new GFG();
Console.WriteLine(obj.maxCoins(t, a, b));
}
}
function maxCoins(t, a, b)
{
let n = a.length;
let boxes = [];
// Store (coins per plate, number of plates) for each
// box
for (let i = 0; i < n; i++) {
boxes.push([ b[i], a[i] ]);
}
// Sort boxes in decreasing order of coins per plate
boxes.sort((x, y) => y[0] - x[0]);
let res = 0;
// Take plates greedily from boxes with maximum coins
// per plate
for (let i = 0; i < n && t > 0; i++) {
let take = Math.min(t, boxes[i][1]);
res += take * boxes[i][0];
t -= take;
}
return res;
}
// Driver Code
let t = 3;
let a = [ 1, 2, 3 ];
let b = [ 3, 2, 1 ];
console.log(maxCoins(t, a, b));
Output
7