Given N different tasks to be completed where the ith task belongs to a certain category, denoted by category[i], and has an associated reward represented by reward[i].
The objective is to determine the optimal order in which to complete these tasks to maximize the total reward. The reward obtained for completing a task is calculated as the product of the reward for that task and the number of distinct categories of tasks completed before (including the current task’s category).
Find the maximum possible total reward that can be achieved by strategically ordering the completion of tasks.
Examples:
Input: N = 4, category = [3, 1, 2, 3] and reward = [2, 1, 4, 4] Output: 29 Explanation: For the given input, the optimal order of completion is as follows:
- Complete the 2nd task: category[2] = 1, reward[2] = 1, number of distinct categories completed = 1, resulting in a profit of 1 x 1 = 1.
- Complete the 1st task: category[1] = 3, reward[1] = 2, number of distinct categories completed = 2, resulting in a profit of 2 x 2 = 4.
- Complete the 3rd task: category[3] = 2, reward[3] = 4, number of distinct categories completed = 3, resulting in a profit of 4 x 3 = 12.
- Complete the 4th task: category[4] = 3, reward[4] = 4, number of distinct categories completed = 3, resulting in a profit of 4 x 3 = 12.
Therefore, the total profit is 1 + 4 + 12 + 12 = 29.
Input: N = 6, category = [2, 2, 2, 1, 3, 3], reward = [1, 2, 6, 4, 3, 5] Output: 58 Explanation: For the given input, the optimal order of completion is as follows:
- Complete the 1st task: category[1] = 2, reward[1] = 1, number of distinct categories completed = 1, resulting in a profit of 1 x 1 = 1.
- Complete the 5th task: category[5] = 3, reward[5] = 3, number of distinct categories completed = 2, resulting in a profit of 2 x 3 = 6.
- Complete the 4th task: category[4] = 1, reward[4] = 4, number of distinct categories completed = 3, resulting in a profit of 3 x 4 = 12.
- Complete the 2nd task: category[2] = 2, reward[2] = 2, number of distinct categories completed = 3, resulting in a profit of 3 x 2 = 6.
- Complete the 6th task: category[6] = 3, reward[6] = 5, number of distinct categories completed = 3, resulting in a profit of 3 x 5 = 15.
- Complete the 3rd task: category[3] = 2, reward[3] = 6, number of distinct categories completed = 3, resulting in a profit of 3 x 6 = 18.
Therefore, the total profit is 1 + 6 + 12 + 6 + 15 + 18 = 58.
Approach: To solve the problem, follow the below idea:
The problem can be solved by taking one task with minimum reward from each category and perform them in increasing order of their reward. For the remaining tasks, they can be performed in any order as all the categories would have been covered earlier.
Step-by-step algorithm:
- Initialize two maps: categorySumOfRewards to store the sum of rewards for each task category, and categoryMinimumReward to store the minimum reward for each task category.
- Iterate through the tasks, updating the maps based on the task category and reward.
- Create a vector minRewards to store the minimum rewards for each category and initialize maxTotalReward to 0.
- Iterate through categorySumOfRewards, calculate the contribution to maxTotalReward for each category by subtracting the minimum reward and multiplying it by the count of distinct categories completed before.
- Sort minRewards in ascending order.
- Iterate through minRewards, adding additional rewards to maxTotalReward based on the sorted minimum rewards.
- Return maxTotalReward as the maximum possible total reward.
Below is the implementation of the approach:
C++
#include <bits/stdc++.h>
using namespace std;
long findMaximumTotalReward(vector< int >& taskCategories,
vector< int >& taskRewards)
{
map< int , long long > categorySumOfRewards;
map< int , int > categoryMinimumReward;
int n = taskCategories.size();
for ( int i = 0; i < n; i++) {
if (!categorySumOfRewards.count(taskCategories[i])) {
categorySumOfRewards.insert({ taskCategories[i], 0 });
}
categorySumOfRewards[taskCategories[i]]
+= taskRewards[i];
if (!categoryMinimumReward.count(
taskCategories[i])) {
categoryMinimumReward.insert(
{ taskCategories[i], INT_MAX });
}
categoryMinimumReward[taskCategories[i]]
= min(categoryMinimumReward[taskCategories[i]],
taskRewards[i]);
}
vector< int > minRewards;
long long maxTotalReward = 0LL;
int categoryCount = categoryMinimumReward.size();
for ( auto it = categorySumOfRewards.begin();
it != categorySumOfRewards.end(); ++it) {
int taskCategory = it->first;
long long sum = it->second;
maxTotalReward += ( long long )
(sum - categoryMinimumReward[taskCategory])
* (categoryCount);
minRewards.push_back(
categoryMinimumReward[taskCategory]);
}
sort(minRewards.begin(), minRewards.end());
for ( int i = 0; i < minRewards.size(); i++) {
maxTotalReward
+= ( long long )minRewards[i] * (i + 1);
}
return ( long )maxTotalReward;
}
int main()
{
vector< int > taskCategories = { 3, 1, 2, 3 };
vector< int > taskRewards = { 2, 1, 4, 4 };
cout << "Max Total Rewards: "
<< findMaximumTotalReward(taskCategories,
taskRewards)
<< endl;
return 0;
}
|
Java
import java.util.*;
public class Main {
static long findMaximumTotalReward(ArrayList<Integer> taskCategories, ArrayList<Integer> taskRewards) {
HashMap<Integer, Long> categorySumOfRewards = new HashMap<>();
HashMap<Integer, Integer> categoryMinimumReward = new HashMap<>();
int n = taskCategories.size();
for ( int i = 0 ; i < n; i++) {
categorySumOfRewards.put(taskCategories.get(i), categorySumOfRewards.getOrDefault(taskCategories.get(i), 0L) + taskRewards.get(i));
categoryMinimumReward.put(taskCategories.get(i), Math.min(categoryMinimumReward.getOrDefault(taskCategories.get(i), Integer.MAX_VALUE), taskRewards.get(i)));
}
ArrayList<Integer> minRewards = new ArrayList<>();
long maxTotalReward = 0L;
int categoryCount = categoryMinimumReward.size();
for (Map.Entry<Integer, Long> entry : categorySumOfRewards.entrySet()) {
int taskCategory = entry.getKey();
long sum = entry.getValue();
maxTotalReward += (sum - categoryMinimumReward.get(taskCategory)) * categoryCount;
minRewards.add(categoryMinimumReward.get(taskCategory));
}
Collections.sort(minRewards);
for ( int i = 0 ; i < minRewards.size(); i++) {
maxTotalReward += minRewards.get(i) * (i + 1 );
}
return maxTotalReward;
}
public static void main(String[] args) {
ArrayList<Integer> taskCategories = new ArrayList<>(Arrays.asList( 3 , 1 , 2 , 3 ));
ArrayList<Integer> taskRewards = new ArrayList<>(Arrays.asList( 2 , 1 , 4 , 4 ));
System.out.println( "Max Total Rewards: " + findMaximumTotalReward(taskCategories, taskRewards));
}
}
|
Python3
def find_maximum_total_reward(task_categories, task_rewards):
category_sum_of_rewards = {}
category_minimum_reward = {}
n = len (task_categories)
for i in range (n):
if task_categories[i] not in category_sum_of_rewards:
category_sum_of_rewards[task_categories[i]] = 0
category_sum_of_rewards[task_categories[i]] + = task_rewards[i]
if task_categories[i] not in category_minimum_reward:
category_minimum_reward[task_categories[i]] = float ( 'inf' )
category_minimum_reward[task_categories[i]] = min (
category_minimum_reward[task_categories[i]],
task_rewards[i]
)
min_rewards = []
max_total_reward = 0
for task_category, reward_sum in category_sum_of_rewards.items():
sum_rewards = reward_sum
max_total_reward + = (sum_rewards -
category_minimum_reward[task_category]) * len (category_minimum_reward)
min_rewards.append(category_minimum_reward[task_category])
min_rewards.sort()
for i in range ( len (min_rewards)):
max_total_reward + = min_rewards[i] * (i + 1 )
return max_total_reward
task_categories = [ 3 , 1 , 2 , 3 ]
task_rewards = [ 2 , 1 , 4 , 4 ]
print ( "Max Total Rewards:" , find_maximum_total_reward(task_categories, task_rewards))
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static long FindMaximumTotalReward(List< int > taskCategories, List< int > taskRewards)
{
Dictionary< int , long > categorySumOfRewards = new Dictionary< int , long >();
Dictionary< int , int > categoryMinimumReward = new Dictionary< int , int >();
int n = taskCategories.Count;
for ( int i = 0; i < n; i++)
{
if (!categorySumOfRewards.ContainsKey(taskCategories[i]))
{
categorySumOfRewards[taskCategories[i]] = 0;
}
categorySumOfRewards[taskCategories[i]] += taskRewards[i];
if (!categoryMinimumReward.ContainsKey(taskCategories[i]))
{
categoryMinimumReward[taskCategories[i]] = int .MaxValue;
}
categoryMinimumReward[taskCategories[i]] = Math.Min(categoryMinimumReward[taskCategories[i]], taskRewards[i]);
}
List< int > minRewards = new List< int >();
long maxTotalReward = 0;
int categoryCount = categoryMinimumReward.Count;
foreach ( var entry in categorySumOfRewards)
{
int taskCategory = entry.Key;
long sum = entry.Value;
maxTotalReward += (sum - categoryMinimumReward[taskCategory]) * categoryCount;
minRewards.Add(categoryMinimumReward[taskCategory]);
}
minRewards.Sort();
for ( int i = 0; i < minRewards.Count; i++)
{
maxTotalReward += minRewards[i] * (i + 1);
}
return maxTotalReward;
}
static void Main( string [] args)
{
List< int > taskCategories = new List< int > { 3, 1, 2, 3 };
List< int > taskRewards = new List< int > { 2, 1, 4, 4 };
Console.WriteLine( "Max Total Rewards: " + FindMaximumTotalReward(taskCategories, taskRewards));
}
}
|
Javascript
function findMaximumTotalReward(taskCategories, taskRewards) {
let categorySumOfRewards = {};
let categoryMinimumReward = {};
let n = taskCategories.length;
for (let i = 0; i < n; i++) {
if (!categorySumOfRewards.hasOwnProperty(taskCategories[i])) {
categorySumOfRewards[taskCategories[i]] = 0;
}
categorySumOfRewards[taskCategories[i]] += taskRewards[i];
if (!categoryMinimumReward.hasOwnProperty(taskCategories[i])) {
categoryMinimumReward[taskCategories[i]] = Number.MAX_SAFE_INTEGER;
}
categoryMinimumReward[taskCategories[i]] = Math.min(categoryMinimumReward[taskCategories[i]], taskRewards[i]);
}
let minRewards = [];
let maxTotalReward = 0;
let categoryCount = Object.keys(categoryMinimumReward).length;
for (let taskCategory in categorySumOfRewards) {
let sum = categorySumOfRewards[taskCategory];
maxTotalReward += (sum - categoryMinimumReward[taskCategory]) * categoryCount;
minRewards.push(categoryMinimumReward[taskCategory]);
}
minRewards.sort((a, b) => a - b);
for (let i = 0; i < minRewards.length; i++) {
maxTotalReward += minRewards[i] * (i + 1);
}
return maxTotalReward;
}
let taskCategories = [3, 1, 2, 3];
let taskRewards = [2, 1, 4, 4];
console.log( "Max Total Rewards: " + findMaximumTotalReward(taskCategories, taskRewards));
|
Output
Max Total Rewards: 29
Time Complexity: O(N * log N), where N is the number of tasks. Auxiliary Space: O(C), where C is the number of distinct task categories.
|