5982. 解决智力问题


倒序DP
可以记dp[i]为从[i, n-1]范围内得到的最高分数,那么反向遍历questions,对于每个i来说,有两种情况:
- 不解决此问题:dp[i] = dp[i + 1]
- 解决此问题,需要跳过后面一些问题,记下一个能够做的问题的下标为j,j = i + brainpower_i + 1:
- 如果j大于n的话,那么后面的问题都不能做,dp[i] = point_i
- 如果j小于n的话,dp[i] = point[i] + dp[j]
class Solution {public:long long mostPoints(vector<vector<int>> &questions) {int n = questions.size();vector<long long> dp(n + 1);for(int i = n - 1; i >= 0; i--) {auto &q = questions[i];int j = i + q[1] + 1;dp[i] = max(dp[i + 1], q[0] + (j < n ? dp[j] : 0));}return dp[0];}};
正序刷表
另一种做法是刷表法:用当前状态,去更新当前状态所影响的状态。
定义 f[i] 表示解决区间 [0,i] 内的问题可以获得的最高分数。
对于问题 i,若跳过,则可以更新f[i+1]=max(f[i+1], f[i])。
若不跳过,记 j=i + brainpower[i] + 1,则可以更新f[j]=max(f[j], f[i]+point[i])。
对于 i=n−1 和 j≥n 的情况,为了简化代码逻辑,我们可以将其更新到 f[n] 中。
最后答案为 f[n]。class Solution {public:long long mostPoints(vector<vector<int>> &questions) {int n = questions.size();vector<long long> f(n + 1);for (int i = 0; i < n; ++i) {f[i + 1] = max(f[i + 1], f[i]);auto &q = questions[i];int j = min(i + q[1] + 1, n);f[j] = max(f[j], f[i] + q[0]);}return f[n];}};
