题意
给定 天的安排,每天有两种选择:
- 学习:获得
点知识,压力值增加
。
- 做博丽灵梦:不获得知识,压力值减少
(减后若为负则视为
)。
初始压力值为 ,要求在每一天结束后,压力值都必须满足
。求
天后能获得的最大知识量。
题解
既然涉及每天的决策,并且由于数据范围较小(),很显然可以利用**动态规划(DP)**来求解。
我们考虑将当前的“压力值”作为状态。设 表示在某一天的决策结束后,压力值恰好为
时所能获得的最大知识量。初始时,第
天
,其余状态由于无法到达,设为一个极小值(如
)。
对于第 天,我们枚举前一天的所有可能的合法压力值
,并尝试进行转移:
- 如果选择学习:这会使得压力值增加
。我们需要判断
是否超过了上限
。如果
,则可以用新获得的知识量来更新后续的状态:
- 如果选择做博丽灵梦:这会使得压力值减少
。由于题目特别说明了“减为负数则视为
”,所以决策后的新压力值为
。此时知识量不会增加:
每天计算完毕后,将 滚动替换掉
数组即可。最终答案即为
天结束后,所有有效状态
中的最大值。
复杂度
- 时间复杂度:
- 空间复杂度:
参考代码与链接
#include <bits/stdc++.h>
using namespace std;
void solve() {
int n, m;
cin >> n >> m;
vector<long long> a(n), b(n);
for (int i = 0; i < n; ++i) cin >> a[i];
for (int i = 0; i < n; ++i) cin >> b[i];
vector<long long> dp(m + 1, -1);
dp[0] = 0;
for (int i = 0; i < n; ++i) {
vector<long long> ndp(m + 1, -1);
for (int j = 0; j <= m; ++j) {
if (dp[j] == -1) continue;
// 选择学习
if (j + b[i] <= m) {
ndp[j + b[i]] = max(ndp[j + b[i]], dp[j] + a[i]);
}
// 选择做博丽灵梦
int nj = max(0LL, j - b[i]);
ndp[nj] = max(ndp[nj], dp[j]);
}
dp = move(ndp);
}
long long ans = 0;
for (int j = 0; j <= m; ++j) {
ans = max(ans, dp[j]);
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int T; cin >> T;
while (T--) solve();
}

京公网安备 11010502036488号