0%

2140. 解决智力问题

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

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

数据范围:

$1\le questions.len \le 10^5; 1\le points_i, brainpower_i \le 10^5$

题解:

考虑选与不选,设 $dp[i]$ 表示以 $i$ 结尾的最大分数。

选 $i$ ,则 $dp[i] = dp[k] + points[i], i \ge k + brainpower[k] + 1$

不选 $i$ ,则 $dp[i] = dp[i - 1]$ 。

但是这样的话需要使用双重循环,时间复杂度太高。

而且存在后效性,选 $i$ 的话会对后面的造成影响,考虑如果反向的话, $dp[i]$ 表示从 $i$ 到最后最大分数。

选 $i$ ,则 $dp[i] = dp[i + brainpower[i] + 1] \or points[i]$ 。

不选 $i$ ,则 $dp[i] = dp[i + 1]$ 。

也可以使用记忆化搜索,根本不用费心思考虑。

代码:

递推

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
auto optimize_cpp_stdio = []()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();
class Solution
{
public:
const static int maxn = 1e5 + 10;
const static int maxm = 1e5 + 10;
const int INF = 0x3f3f3f3f;

long long mostPoints(vector<vector<int>> &questions)
{
int n = questions.size();
vector<long long> dp(n);
dp[n - 1] = questions[n - 1][0];
for (int i = n - 2; i >= 0; --i)
{
// 不选
dp[i] = dp[i + 1];
// 选
if (i + questions[i][1] + 1 < n)
dp[i] = max(dp[i], 1l * questions[i][0] + dp[i + questions[i][1] + 1]);
else
dp[i] = max(dp[i], 1ll * questions[i][0]);
}
return dp[0];
}
};

记忆化搜索

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
auto optimize_cpp_stdio = []()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();
class Solution
{
public:
const static int maxn = 1e5 + 10;
const static int maxm = 1e5 + 10;
const int INF = 0x3f3f3f3f;
vector<long long> dp;
long long dfs(int step, int n, vector<vector<int>> &questions)
{
if (step >= n)
return 0;
if (dp[step] != -1)
return dp[step];
long long ret = 0;
// 不选
return dp[step] = max(dfs(step + 1, n, questions), dfs(step + questions[step][1] + 1, n, questions) + questions[step][0]);
}
long long mostPoints(vector<vector<int>> &questions)
{
int n = questions.size();
dp.resize(n, -1);
dfs(0, n, questions);
return dp[0];
}
};