1751: Maximum-Number-of-Events-That-Can-Be-Attended-II
Hard
table of contents
A greedy algorithm seems to be impossible here as we are not able to pre-emptively exclude a meeting without considering all the other meetings around them.
Therefore, it makes sense to iterate through the entire solution
space and use a dp
algorithm to store our values and
maximise our values from attending events. In our case, we have
dp[i][j]
, where 0 <= i < k
denotes the
number of events we can afford to attend, and
0 <= j < events.size()
denotes the
index of the event we are currently on. Then,
dp[i][j]
denotes the maximum value we can
attain after attending a maximum of i
events and starting
on event index j
.
Now, we have a recursion
recursive algorithm that aims
to iterate through all events and, given an eventIndex
and
k
value, aims to return the maximum value
we can attain after attending a maximum of k
events after
starting on event index eventIndex
.
During the recursion
recursive algorithm, for each event
we can choose to either:
- attend the event
- if we attend, we can return the sum the current
value of the event, and recursively run
recursion
withk-1
starting from the next possible event index
- if we attend, we can return the sum the current
value of the event, and recursively run
- NOT attend the event
- if we don’t, we can return the result after recursively
running
recursion
withk
starting from indexeventIndex + 1
- if we don’t, we can return the result after recursively
running
Since recursion
returns the maximum
value we can attain, by choosing the maximum possible value out
of the results after attending or not attending the
event, we can set dp[k][eventIndex]
to that value, and
simply return it.
This might make more sense if you read the code-
code
class Solution {
public:
int recursion(int eventIndex, vector<vector<int>>& events, int k, vector<vector<int>> &dp) {
if (eventIndex >= events.size() || eventIndex == -1 || k == 0) {
return 0;
}
if (dp[k][eventIndex] != -1) {
return dp[k][eventIndex];
}
int l = eventIndex;
int r = events.size()-1;
int res = -1;
while (l <= r) {
int mid = l + (r - l)/2;
if (events[mid][0] > events[eventIndex][1]) {
= mid;
res = mid-1;
r } else {
= mid+1;
l }
}
int outcome1 = events[eventIndex][2] + recursion(res, events, k-1, dp);
int outcome2 = recursion(eventIndex+1, events, k, dp);
[k][eventIndex] = max(outcome1, outcome2);
dpreturn dp[k][eventIndex];
}
int maxValue(vector<vector<int>>& events, int k) {
(events.begin(), events.end());
sort<vector<int>> dp (k+1, vector<int>(events.size(), -1));
vectorreturn recursion(0, events, k, dp);
}
};