-
Notifications
You must be signed in to change notification settings - Fork 4.9k
/
MaximumNumberOfEventsThatCanBeAttended.II.cpp
195 lines (164 loc) · 6.72 KB
/
MaximumNumberOfEventsThatCanBeAttended.II.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
// Source : https://leetcode.com/problems/maximum-number-of-events-that-can-be-attended-ii/
// Author : Hao Chen
// Date : 2021-02-16
/*****************************************************************************************************
*
* You are given an array of events where events[i] = [startDayi, endDayi, valuei]. The ith event
* starts at startDayi and ends at endDayi, and if you attend this event, you will receive a value of
* valuei. You are also given an integer k which represents the maximum number of events you can
* attend.
*
* You can only attend one event at a time. If you choose to attend an event, you must attend the
* entire event. Note that the end day is inclusive: that is, you cannot attend two events where one
* of them starts and the other ends on the same day.
*
* Return the maximum sum of values that you can receive by attending events.
*
* Example 1:
*
* Input: events = [[1,2,4],[3,4,3],[2,3,1]], k = 2
* Output: 7
* Explanation: Choose the green events, 0 and 1 (0-indexed) for a total value of 4 + 3 = 7.
*
* Example 2:
*
* Input: events = [[1,2,4],[3,4,3],[2,3,10]], k = 2
* Output: 10
* Explanation: Choose event 2 for a total value of 10.
* Notice that you cannot attend any other event as they overlap, and that you do not have to attend k
* events.
*
* Example 3:
*
* Input: events = [[1,1,1],[2,2,2],[3,3,3],[4,4,4]], k = 3
* Output: 9
* Explanation: Although the events do not overlap, you can only attend 3 events. Pick the highest
* valued three.
*
* Constraints:
*
* 1 <= k <= events.length
* 1 <= k * events.length <= 106
* 1 <= startDayi <= endDayi <= 109
* 1 <= valuei <= 106
******************************************************************************************************/
class Solution {
private:
static const bool comp_start(vector<int>& x, vector<int>& y) {
if ( x[0] != y[0] ) return x[0] < y[0];
return x[1] < y[1];
}
static const bool comp_end(vector<int>& x, vector<int>& y) {
if ( x[1] != y[1] ) return x[1] < y[1];
return x[0] < y[0];
}
void print(vector<vector<int>>& events){
cout << "[" ;
for(int i = 0; i<events.size(); i++) {
cout << "[";
for (int j = 0; j < events[i].size(); j++) {
cout << events[i][j] << (j == events[i].size() - 1 ? "":",") ;
}
cout << (i == events.size()-1 ? "]": "],") ;
}
cout << "]" << endl;
}
public:
int maxValue(vector<vector<int>>& events, int k) {
//Solution3 - DP
std::sort(events.begin(), events.end(), comp_end);
return maxValueDP(events, k);
std::sort(events.begin(), events.end(), comp_start);
//Solution 2 - DFS with cache --> Time Limit Exceeded
vector<vector<int>> cache(events.size()+1, vector<int>(k+1, -1));
return maxValueDFS(events, 0, k, cache);
//Solution 1 - DFS --> Time Limit Exceeded
return maxValueDFS(events, 0, k);
}
//binary search to find the first event which start day is greater than the `day`
/*
* for (int i = low; i < events.size(); i++) {
* if ( events[i][0] > day ) break;
* }
*/
int findNextEvent(vector<vector<int>>& events, int low, int day) {
int high = events.size() - 1;
while (low < high) {
int mid = low + (high - low) / 2;
if ( events[mid][0] <= day) {
low = mid + 1;
}else{
high = mid;
}
}
return ( events[low][0] > day ) ? low : low+1;
}
int maxValueDFS(vector<vector<int>>& events, int current, int k) {
if (current >= events.size() || k == 0 ) return 0;
// if we select the events[index], then find the next events
int next = findNextEvent(events, current, events[current][1]);
// we have two choice, attend the event or not
int attend = events[current][2] + maxValueDFS(events, next, k-1);
int skip = maxValueDFS(events, current + 1, k);
return std::max(attend, skip);
}
int maxValueDFS(vector<vector<int>>& events, int current, int k, vector<vector<int>>& cache) {
if (current >= events.size() || k == 0 ) return 0;
//if find in cache, then return
if (cache[current][k] != -1) return cache[current][k];
// if we select the events[index], then find the next events
int next = findNextEvent(events, current, events[current][1]);
// we have two choice, attend the event or not
int attend = events[current][2] + maxValueDFS(events, next, k-1);
int skip = maxValueDFS(events, current + 1, k);
return cache[current][k] = std::max(attend, skip);
}
//binary search to find the nearest previous event which ending day is less than the `day`
/*
* for (int i = high; i >= 0; i++) {
* if ( events[i][1] < day ) break;
* }
*/
int findPrevEvent(vector<vector<int>>& events, int high, int day) {
int low = 0;
while (low < high) {
int mid = low + (high - low) / 2;
if ( events[mid][1] < day) {
low = mid + 1;
}else{
high = mid;
}
}
return low - 1;
}
int maxValueDP(vector<vector<int>>& events, int k) {
// for each event, find the previous nearest event which
// ending day is less than its starting day
for (int i = 0; i < events.size(); i++) {
events[i].push_back( findPrevEvent(events, i, events[i][0]));
}
//print(events);
vector<vector<int>> dp(events.size(), vector<int>(k, 0));
//---== initial the dp table ==---
//if we only have first event
for(int i = 0; i<k; i++) {
dp[0][i] = events[0][2];
}
//if we only can attend one event.
for (int i = 1; i < events.size(); i++) {
dp[i][0] = max(dp[i-1][0], events[i][2]);
}
for (int times = 1; times<k; times++) {
for (int current = 1; current < events.size(); current++) {
int prev = events[current][3];
int attend = (prev == -1) ?
events[current][2]: // not found the previous event
dp[prev][times-1] + events[current][2]; //found previouse event
int skip = dp[current-1][times];
dp[current][times] = max (attend, skip );
}
}
//print (dp);
return dp.back().back();
}
};