
Input: ‘N’ = 4, ‘ARR’ = [8, 6, 6, 20]
Output: 34
In this case, the maximum possible happiness can be achieved by selecting the order: [0, 1, 3] or [0, 2, 3]. The sum of happiness for both order will be 8 + 6 + 20 = 34.
The first line will contain the integer ‘T’, the number of test cases.
Each test case consists of two lines.
The first line of input contains one integer, ‘N’, the number of matches scheduled.
Followed by a line containing space-separated ‘N’ positive integers, denoting the elements of the array ‘ARR’.
For each test case, print the maximum achievable total happiness.
You don't need to print anything. It has already been taken care of. Just implement the given function.
1 <= ‘T’ <= 10
1 <= ‘N’ <= 10^5
0 <= ‘ARR[i]’ <= 10^4
It is guaranteed that sum of ‘N’ over all test cases is <= 10^5
Time Limit: 1 sec
The idea for this approach is to try out every possible way to watch the matches and pick the order that gives us the maximum total happiness. This can be done using a recursive algorithm because the subproblem to pick order will be the same for every index of the matches.
So let’s suppose we are at index ‘i’, then we have four possibilities to watch matches from here onwards:
While implementing the above algorithm we will return the maximum happiness possible for that index. And also we have to take care of the cases when the ‘i+1’th and the ‘i+2’th index doesn’t exist.
Algorithm:
// This function will return the maximum total happiness possible from the index ‘i’.
Int getMax(i, N, ARR)
// The function will return the maximum total happiness possible.
Int maxHappiness(N, ARR)
In the previous brute force approach, we tried out every possible order to watch matches and pick the one that gives maximum total happiness among all possible combinations. But if we observe more precisely there are many overlapping subproblems, that are recalculated again and again which in turn increases the time complexity.
For e.g. if we are index ‘X’ then we make a recursive call to find the maximum happiness for the indices ‘X+1’, ‘X+2’, ‘X+3’, and ‘X+4’.
Now at index ‘X+1’, we will make a recursive call to find the maximum happiness for the indices ‘X+2’, ‘X+3’, ‘X+4’, and ‘X+5’.
So it clearly visible that the maximum total happiness for the index ‘X+2’, ‘X+3’, and ‘X+4’ is recalculated which can be avoided if we memoize the maximum total happiness for this index in the first time of calculation.
We can create an array, let’s call it ‘DP’ of length ‘N’. Where ‘DP[i]’ denotes the maximum total happiness achievable from the index ‘i’ to ‘N-1’.
// This function will return the maximum total happiness possible from the index ‘i’.
Int getMax(i, N, ARR, DP)
// The function will return the maximum total happiness possible.
Int maxHappiness(N, ARR)
In the above memoization approach, we store the maximum total happiness value possible for every index ‘0’ to ‘N-1’ in the ‘DP’ array, but if we observe more precisely for any index ‘i’ we only need the ‘DP’ value for indices ‘i+1’, ‘i+2’, ‘i+3’ and ‘i+4’ respectively.
And if we look at it in a reverse manner, we only need the values of indices ‘i-4’, ‘i-3’, ‘i-2’, and ‘i-1’ only, the ‘DP’ definition for this reverse manner will be :
‘DP[i]’, denotes the maximum possible total happiness we can get by watching the matches from ‘0’th to ‘i’th index.
And the transition will be:
DP[i] = max(DP[i-1], ARR[i] + DP[i-2], ARR[i] + ARR[i-1] + DP[i-3], ARR[i] + ARR[i-1] + ARR[i-2] + DP[i-4]).
So we can maintain a ‘DP’ array of length ‘4’ and update the ‘DP’ value accordingly before moving to the next index.
// The function will return the maximum total happiness possible.
Int maxHappiness(N, ARR)