CF1442D-Sum
Sum
You are given non-decreasing arrays of non-negative numbers.
Vasya repeats the following operation times:
- Selects a non-empty array.
- Puts the first element of the selected array in his pocket.
- Removes the first element from the selected array.
Vasya wants to maximize the sum of the elements in his pocket.
solution
1、通过微调。
首先在最终状态下,假设数组 中的元素分别被取到了 (并没有取完),且 。
由于数组内元素不降的性质,可以得知 ,那么 。
可以之前发现取 是不一定比 优的。
因此可以得到一条结论:在最终状态下,最多只会存在一个数组 被取了部分。
2、冻柜
对于其他的数组,要么不选,要么全选。
那么就可以将其转化为 个具有大小、价值的物品,进行 背包。
枚举那个被取了部分的数组 ,枚举数组 被取出的元素的个数,时间复杂度为 的。
3、分治优化
令 。
在位于 中的数组 ,都需要来自 的数组的 dp 值。
那么对于 中的数组 ,可以将 的 dp 值预处理出来。
该过程可以递归操作,直到 的时候,对于第 个数组,需要的 dp 值是都已经求出来的。
时间复杂度降到 。
code
点击查看代码
#include <bits/stdc++.h>
using namespace std;
vector<long long> a[3010];
long long dp[3010], sum[3010], len[3010], n, k;
long long DFS(int l, int r)
{
if (l == r) {
long long res = 0, ans = -1;
for (int i = 0; i <= min(k, len[l]); i ++ ) {
ans = max(ans, dp[k - i] + res);
if (i < len[l]) res += a[l][i];
}
return ans;
}
long long f[3010], mid = (l + r) >> 1, ans = -1;
memcpy(f, dp, sizeof(dp));
// 对于[l,mid]的数组,预处理(mid,r]的dp值
for (int i = mid + 1; i <= r; i ++ )
for (int j = k; j >= len[i]; j -- )
dp[j] = max(dp[j], dp[j - len[i]] + sum[i]);
ans = max(ans, DFS(l, mid)); // 递归
memcpy(dp, f, sizeof(f));
for (int i = l; i <= mid; i ++ )
for (int j = k; j > len[i]; j -- )
dp[j] = max(dp[j], dp[j - len[i]] + sum[i]);
ans = max(ans, DFS(mid + 1, r));
return ans;
}
int main()
{
scanf("%lld%lld", &n, &k);
for (int i = 1, x; i <= n; i ++ ) {
scanf("%lld", &len[i]);
for (int j = 1; j <= len[i]; j ++ ) {
scanf("%lld", &x);
a[i].push_back(x); sum[i] += x;
}
}
printf("%lld", DFS(1, n));
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】