[LC]2140.解决智力问题

题目

给你一个下标从 0 开始的二维整数数组 questions ,其中 questions[i] = [pointsi, brainpoweri]

这个数组表示一场考试里的一系列题目,你需要 按顺序 (也就是从问题 0 开始依次解决),针对每个问题选择 解决 或者 跳过 操作。解决问题 i 将让你 获得 pointsi 的分数,但是你将 无法 解决接下来的 brainpoweri 个问题(即只能跳过接下来的 brainpoweri 个问题)。如果你跳过问题 i ,你可以对下一个问题决定使用哪种操作。

比方说,给你

1
questions = [[3, 2], [4, 3], [4, 4], [2, 5]]
  • 如果问题 0 被解决了, 那么你可以获得 3 分,但你不能解决问题 12
  • 如果你跳过问题 0 ,且解决问题 1 ,你将获得 4 分但是不能解决问题 23

请你返回这场考试里你能获得的 最高 分数。

分析

考虑用$dp[i]$表示解决前$i$道题目可以获得的最高分数,此时有两种情况:

  • 如果不解决第$i$道题目,那么$dp[i] = dp[i - 1]$.
  • 如果解决第$i$道题目,那么$dp[i] = points[i] + max(0, max_{0 \leq j < i, j + brainpower[j] < i}{dp[j]})$.

时间复杂度为$O(n^2)$.

后效性

对于每一道题目,解决与否不会影响前面的题目,因此可以考虑反方向定义状态,即$dp[i]$表示解决第$i$道题目及以后的题目可以获得的最高分数,那么有状态转移方程:

  • 如果不解决第$i$道题目,那么$dp[i] = dp[i + 1]$.
  • 如果解决第$i$道题目,那么$dp[i] = points[i] + dp[i + brainpower[i] + 1]$.

注意,需要考虑数组越界的问题,如果越界,那么$dp[i] = 0, i >= n$.

代码

1
2
3
4
5
6
7
8
9
10
11
class Solution {
public:
long long mostPoints(vector<vector<int>>& questions) {
int n = questions.size();
auto dp = vector<unsigned long long>(n + 1, 0);
for (int i = n - 1; i >= 0; --i) {
dp[i] = max(dp[i + 1], questions[i][0] + dp[min(n, i + questions[i][1] + 1)]);
}
return dp[0];
}
};

时间复杂度: $O(n)$.

空间复杂度:$O(n)$.


[LC]2140.解决智力问题
https://erlsrnby04.github.io/2024/10/31/LC-2140-解决智力问题/
作者
ErlsrnBy04
发布于
2024年10月31日
许可协议