递归枚举(超时):
class Solution {
public long mostPoints(int[][] questions) {
// 最后结果
long[] finalAns = new long[1];
backtrace(finalAns, 0, questions, 0);
return finalAns[0];
}
// 递归处理
public void backtrace(long[] finalAns, long ans, int[][] questions, int pos) {
// 当位置超出实际的长度时,直接检查最大值,结束递归
if(pos >= questions.length){
// 设置最大值
finalAns[0] = Math.max(finalAns[0], ans);
return;
}
// 以ans为起始得分, 依次处理pos及其后面的元素
// 并直接计算出下一次递归调用的开始位置
for(int i = pos; i < questions.length; i++){
backtrace(finalAns, ans + questions[i][0], questions, i + questions[i][1] + 1);
}
}
}
递归枚举 + 减枝(略微超时):
class Solution {
public long mostPoints(int[][] questions) {
// [0,questions.length - 1]存储中间节点的最大值
// dp[dp.length - 1]存储最后的最大值
long[] dp = new long[questions.length + 1];
backtrace(dp, 0, questions, 0);
// 返回最大值
return dp[dp.length - 1];
}
// 递归调用
public void backtrace(long[] dp, long ans, int[][] questions, int pos) {
// 检查位置,设置最大值
if(pos >= questions.length){
dp[dp.length - 1] = Math.max(dp[dp.length - 1], ans);
return;
}
for(int i = pos; i < questions.length; i++){
long thisAns = ans + questions[i][0];
if(dp[i] > thisAns)
// 当前计算该位置的值thisAns,小于当前dp[i]的值,则直接跳过
continue;
else
// 当前计算该位置的值thisAns,大于当前dp[i]的值,则更新
dp[i] = thisAns;
backtrace(dp, thisAns, questions, i + questions[i][1] + 1);
}
}
}
动态规划(倒序):
class Solution {
public:
long long mostPoints(vector<vector<int>>& questions) {
long long dp[questions.size()];
for(int i = questions.size() - 1; i >= 0; i--){
// 可以走到的最短位置
int prevInd = questions[i][1] + i + 1;
// 这个最短位置的得分,超出范围视为0
long long prevVal = prevInd >= questions.size() ? 0 : dp[prevInd];
// 当前的值
dp[i] = prevVal + questions[i][0];
// 如果没有越界,比较dp[i+1]与do[i]的大小
if(i + 1 < questions.size() && dp[i] < dp[i + 1])
dp[i] = dp[i + 1];
}
return dp[0];
}
};
TODO
动态规划(正序):
class Solution {
public:
long long mostPoints(vector<vector<int>>& questions) {
long long dp[questions.size() + 1];
// TODO
return dp[dp.size() - 1];
}
};