正经题解|大盗杰瑞
2024-05-13 11:47:16
发布于:浙江
69阅读
0回复
0点赞
题意解析
我们可以把所有楼层分为两类:
- 「只能通过楼梯到达」的楼层
- 「可以通过电梯到达」的楼层
定义 为到达楼层 能够拿到的金币数量。
对于「只能通过楼梯到达」的楼层,那么 ,这种情况比较简单。
对于「可以通过电梯到达」的楼层,除了 外,我们还可以从之前含有电梯的楼层到达,即:$\max{f(j)} + A_i \ (j - 1 \vert K,\ 1 \le j \le N) $。这种情况我们似乎要遍历之前的所有「可以通过电梯」到达的楼层来求取 ,但是事实上,我们可以使用一个变量 来维护 。
那么转移便转化为了 。
这样这种情况下的状态转移也只需要 的时间复杂度得到。
接下来我们看下如何处理 「有安保的楼层」。
对于「有安保的楼层」,我们可以将以上讨论的两种楼层合并,直接跳转到下一个「可以通过电梯到达」的楼层即可。即:当前楼层为 ,若 ,则跳转到楼层 。
这样我们便处理了所有情况,要注意的是,不一定到达最后一个楼层获得的金币是最多的,对于本题答案为 。
AC 代码
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int _; cin >> _;
while (_--) {
int n, k;
cin >> n >> k;
vector<int> a(n);
for (auto &x : a) cin >> x;
vector<i64> dp(n + 1);
dp[0] = a[0];
i64 preMax = dp[0];
int i = 1;
while (i < n) {
if (a[i] == -1) {
i = (i / k + 1) * k;
continue;
}
if (i % k == 0) {
dp[i] = max(preMax, dp[i - 1]) + a[i];
preMax = dp[i];
}
else {
dp[i] = dp[i - 1] + a[i];
}
i++;
}
cout << *max_element(begin(dp), end(dp)) << '\n';
}
return 0;
}
复杂度分析
动态规划的状态数为 个,转移的时间复杂度为 ,总的时间复杂度为 。
这里空空如也
有帮助,赞一个