考试策略
你有一场考试,考试时间为 120 分钟。考试有多道题目,你的作答顺序不受限制。对于第 i 道题目,你有三种不同的策略可以选择:
直接跳过这道题目,不花费时间,本题得 0 分。
只做这道题目一部分,花费 p[i] 分钟的时间,本题可以得到 part[i] 分。
做完整道题目,花费 f[i] 分钟的时间,本题可以得到 full[i] 分。
依次给定 4 个数组:p,part,f,full,请你计算出你最多能得到多少分。
样例 1:
输入:
p=[20,50,100,5], part=[20,30,60,3], f=[100,80,110,10], full=[60,55,88,6]
输出:
94
解释:
在所有做题选择中,选择完成整道第 3 题和整道第 4 题的得分最高。整道第 3 题
耗时 110 分钟得到 88 分,整道第 4 题耗时 10 分钟得到 6 分,总共耗时 120 分
钟得到 94 分。
样例 2:
输入:
p=[60,60], part=[30,30], f=[100,120], full=[40,60]
输出:
60
解释:
2 道题目都做一部分和做完整道第 2 题,都能在耗时 120 分钟下得到最高的 60
分。
解答:
定义dp[i][j]为题目数量为i,剩余时间为j时,能得到的最大分数:
对于第i道题:
1. 若不做:
dp[i][j] = dp[i-1][j];
2. 若全做:
dp[i][j] = dp[i-1][j-f[i-1]] + full[i-1] {j >= f[i-1]}
3. 若做一部分:
dp[i][j] = dp[i-1][j-p[i-1]] + part[i-1] {j >= p[i-1]}
4. dp[i][j]取值为 1,2,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) {
// write your code here
/*
定义dp[i][j]为题目数量为i,剩余时间为j时,能得到的最大分数:
对于第i道题:
1. 若不做:
dp[i][j] = dp[i-1][j];
2. 若全做:
dp[i][j] = dp[i-1][j-f[i-1]] + full[i-1] {j >= f[i-1]}
3. 若做一部分:
dp[i][j] = dp[i-1][j-p[i-1]] + part[i-1] {j >= p[i-1]}
4. dp[i][j]取值为 1,2,3三者中最大值
*/
int m = p.size() + 1;
int n = 120 + 1;
int **dp = new int*[m];
for (int i = 0; i < m; i++) {
dp[i] = new int[n];
for (int j = 0; j < n; j++) {
dp[i][j] = 0;
}
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
int nFull = 0;
int nPart = 0;
if(j >= f[i-1]){
nFull = dp[i-1][j-f[i-1]] + full[i-1];
}
if(j >= p[i-1]){
nPart = dp[i-1][j-p[i-1]] + part[i-1];
}
dp[i][j] = std::max(dp[i-1][j], std::max(nFull, nPart));
}
}
int nMax = dp[m-1][n-1];
for (int i = 0; i < m; i++) {
delete[] dp[i];
}
delete[] dp;
return nMax;
}
};