1 条题解
-
0
自动搬运
来自洛谷,原作者为

fighter
**搬运于
2025-08-24 22:10:37,当前版本为作者最后更新于2019-06-13 15:29:40,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
首先有一个非常显然的分段式DP:
设表示前条蛇,改变次大小所得到的最小剩余空间
表示区间的空余空间
那么可以得到如下转移方程:
为我们枚举的一个断点,表示这段区间用同一大小的网。
那么考虑怎么求。
根据定义,一段区间的空余空间一定是用区间中的最大值作为网的大小,减去其他数字得到的和。即,其中区间和可以用前缀和处理。
由于我们的已经是了,所以我们考虑快速(最好是)求出区间最大值。
首先想到的是线段树,但有一只,太慢了。然后发现没有修改操作,可以用表查询搞一搞(没写过不知道效果怎么样)。
但实际上有一种更简洁的方式,由于我们枚举断点的时候会从向下逐一枚举,那么我们可以在枚举断点的时候同时更新最大值。
#include <bits/stdc++.h> #define MAX 405 using namespace std; int n, m; int a[MAX], f[MAX][MAX], s[MAX]; int main() { cin >> n >> m; for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); s[i] = s[i-1]+a[i]; } m++; memset(f, 0x3f, sizeof(f)); f[0][0] = 0; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= min(m, i); ++j) { int mx = a[i]; for (int k = i-1; k >= 0; --k) { f[i][j] = min(f[i][j], f[k][j-1]+mx*(i-k)-(s[i]-s[k])); mx = max(mx, a[k]); } } } int ans = 0x3f3f3f3f; for (int i = 0; i <= m; ++i) { ans = min(ans, f[n][i]); } cout << ans << endl; return 0; }
- 1
信息
- ID
- 4402
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者