273. Test Strategy
You have an exam, which lasts 120 minutes. There are multiple questions on the exam, and your answer order is not limited. There are three different strategies you can choose from for the question i:
Skip this question and get 0 points for no time.
Just do part of the problem. You would spend p[i] minutes and get part[i] points.
Do the whole problem. You would spend f[i] minutes and get full[i] points.
Given four arrays in turn: p, part, f, full, calculate the maximum number of points you can get.
Example
Sample 1:
Input sample: p=[20,50,100,5], part=[20,30,60,3], f=[100,80,110,10], full=[60,55,88,6]
Output sample: 94
Sample explanation: Of all the choices, choosing to complete the whole question 3 and the whole question 4 has the highest score. The whole of question 3 took 110 minutes to get 88 points, and the whole of question 4 took 10 minutes to get 6 points, so it took 120 minutes to get 94 points altogether.
Sample 2:
Input sample: p=[60,60], part=[30,30], f=[100,120], full=[40,60]
Output sample: 60
Sample explanation: You can choose doing part of the problem 1 and 2 or doing the whole of question 2. Either way you can get a maximum of 60 points in 120 minutes .
Clarification
We will run your code for 20times,. please ensure that you don't change the param in your function.
Notice
The number of examination questions is no more than 200 and at least 1.
Time spent on each question: 1 ≤ p[i] ≤ f[i] ≤ 120
Score of each question: 1 ≤ part[i] ≤ full[i] ≤ 100
解法1:
首先这题是01背包型DP。dp[i][j]表示前i道题花了时间j时所得到的最多分数。注意对i要分3种可能:不做,部分做和全部做。
class Solution {
public:
/**
* @param p: The time you choose to do part of the problem.
* @param part: The points you choose to do part of the problem.
* @param f: The time you choose to do the whole problem.
* @param full: The points you choose to do the whole problem.
* @return: Return the maximum number of points you can get.
*/
int exam(vector<int> &p, vector<int> &part, vector<int> &f, vector<int> &full) {
int n = p.size();
vector<vector<int>> dp(n + 1, vector<int>(121, 0));
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= 120; ++j) {
dp[i][j] = dp[i - 1][j]; // case 1: skip question i
if (j >= p[i - 1]) { //case 2: partial question i
dp[i][j] = max(dp[i][j], dp[i - 1][j - p[i - 1]] + part[i - 1]);
}
if (j >= f[i - 1]) { //case 3: full question i
dp[i][j] = max(dp[i][j], dp[i - 1][j - f[i - 1]] + full[i - 1]);
}
}
}
return dp[n][120];
}
};
解法2:滚动数组优化空间。
class Solution {
public:
/**
* @param p: The time you choose to do part of the problem.
* @param part: The points you choose to do part of the problem.
* @param f: The time you choose to do the whole problem.
* @param full: The points you choose to do the whole problem.
* @return: Return the maximum number of points you can get.
*/
int exam(vector<int> &p, vector<int> &part, vector<int> &f, vector<int> &full) {
int n = p.size();
vector<vector<int>> dp(2, vector<int>(121, 0));
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= 120; ++j) {
dp[i % 2][j] = dp[(i - 1) % 2][j]; // case 1: skip question i
if (j >= p[i - 1]) { //case 2: partial question i
dp[i % 2][j] = max(dp[i % 2][j], dp[(i - 1) % 2][j - p[i - 1]] + part[i - 1]);
}
if (j >= f[i - 1]) { //case 3: full question i
dp[i % 2][j] = max(dp[i % 2][j], dp[(i - 1) % 2][j - f[i - 1]] + full[i - 1]);
}
}
}
return dp[n % 2][120];
}
};
解法3:一维数组优化空间。
class Solution {
public:
/**
* @param p: The time you choose to do part of the problem.
* @param part: The points you choose to do part of the problem.
* @param f: The time you choose to do the whole problem.
* @param full: The points you choose to do the whole problem.
* @return: Return the maximum number of points you can get.
*/
int exam(vector<int> &p, vector<int> &part, vector<int> &f, vector<int> &full) {
int n = p.size();
vector<int> dp(121, 0);
for (int i = 1; i <= n; ++i) {
for (int j = 120; j >= min(p[i - 1], f[i - 1]); --j) {
//case 1: dp[j] = dp[j] skip question i
if (j >= p[i - 1]) { //case 2: partial question i
dp[j] = max(dp[j], dp[j - p[i - 1]] + part[i - 1]);
}
if (j >= f[i - 1]) { //case 3: full question i
dp[j] = max(dp[j], dp[j - f[i - 1]] + full[i - 1]);
}
}
}
return dp[120];
}
};