题目:解决治理问题
思路:
这道题看完之后,想到了 从一个节点跳到另外一个节点,就把他想成了深度求数值(dfs实际上求深度有解,而不适用于求极值),求极值贪心和动态规划,实际上这道题是一个动态规划的题;写完dfs时间超时,实际上会处理很多重复位置的值;
动态规划的必备三个条件:重复子问题,最优子结构,状态转移方程
通过动态规划我们可以知道:
动态规划先
1. 需要DP数组存储状态:
2.通过当前状态所依赖的状态,来计算当前状态。
本题能够知道 在 f(i)处 我们只有两个操作:(1) 跳过 (2)解决
所以我们能够推出结果
若跳过,则有 f[i]=f[i+1]。
若解决,则需要跳过后续brainpower[i] 个问题。记 j=i+brainpower[i]+1
最后的即为最大值
难点:
周赛第二次参加 依然A两道 ,不过本周第三道写了dfs,思路出发点错了,有待提高加油!!!
结果:
倒序进行的填表行为
public long mostPoints(int[][] questions) {
//数组长度
int n = questions.length;
int[] dp = new int[n+1];
for (int i = n-1; i >=0 ; i--) {
//判断当前的最大数据 该位置是跳开还是解决
dp[i] = Math.max(dp[i + 1], questions[i][0] + (i + questions[i][1] + 1 < n ? dp[i + questions[i][1] + 1] : 0));
}
return dp[0];
}
解法二:正序 DP(刷表法)
用当前状态,去更新当前状态所影响的状态。
定义 f[i]表示解决区间 [0,i]内的问题可以获得的最高分数。
对于问题 ii,若跳过,则可以更新 f[i+1]=(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 mostPoints(int[][] questions) {
var n = questions.length;
var f = new long[n + 1];
for (var i = 0; i < n; i++) {
//取出最大的f(i)
f[i + 1] = Math.max(f[i + 1], f[i]);
var q = questions[i];
var j = Math.min(i + q[1] + 1, n);
//设置最大的f(j)
f[j] = Math.max(f[j], f[i] + q[0]);
}
return f[n];
}
}
总结:
动态规划、贪心和dfs一定要分清区别