Ngay khi đọc đề bài này, thì nhận ra dạng bài này liền. Trước tiên, bắt tay vào giải đệ quy trước:
- Đầu tiên, tại mỗi question ta có 2 lựa chọn: solve
question i
này hoặc skip tới câu tiếp theoquestion i+1
- Nếu chọn solve
question i
hiện tại, thì ta gain đc point của question hiện tại và skipbrainpower i
question tiếp theo - Nếu skip
question i
, ta tiến thới xétquestion i+1
và tiếp tục xét 2 lựa chọn choquestion i+1
Recursion + memo
class Solution {
private int[][] questions;
private Map<Integer, Long> memo;
public long mostPoints(int[][] questions) {
this.questions = questions;
memo = new HashMap<>();
return solve(0);
}
private long solve(int i) {
if (i >= questions.length) return 0;
if (memo.containsKey(i)) return memo.get(i);
long maxPoint = Math.max(
// select this question (gain questions[i][0] points) i, skip brainpower i question
questions[i][0] + solve(i + questions[i][1] + 1),
solve(i+1) // ignore question i => check next question i + 1
);
memo.put(i, maxPoint);
return maxPoint;
}
}
Sau khi có đc công thức đệ quy, dễ dàng convert thành quy hoạch động (à, thật ra cũng không dễ lắm :)))
class Solution {
public long mostPoints(int[][] questions) {
int n = questions.length;
long[] dp = new long[200001];
for (int i = n-1; i >= 0; i--) {
dp[i] = Math.max(
questions[i][0] + dp[i + questions[i][1] + 1],
dp[i+1]
);
}
return dp[0];
}
}