真正的题目:
给定一个长度为 nnn 的数组,最多切 mmm 刀,分成最多 m+1m+1m+1 段。每一段代价 === 段内最大值 ××× 长度 −−− 段内和。求最小总代价。
输入格式
第一行:两个整数 n,mn,mn,m
第二行:nnn 个整数,表示数组 a1,a2,…,ana_1,a_2,\dots,a_na1 ,a2 ,…,an
输出格式
输出一个整数
输入样例1
输出样例1
样例解析:
最多切 2 刀,分成 3 段。
最优分段:[3,1]、[2,4]、[3]
总代价计算:
第一段:max(3,1)×2 − (3+1) = 3×2−4 = 2
第二段:max(2,4)×2 − (2+4) = 4×2−6 = 2
第三段:max(3)×1 − 3 = 3−3 = 0
总代价:2+2+0 = 4(非最优)
真正最优分段:[3,1,2]、[4]、[3]
代价:3×3−6 + 0 + 0 = 9−6 = 3
官方最优方案:[3,1,2,4]、[3],切 1 刀
代价:4×4−10 + 0 = 16−10 = 6
正确最小代价方案:[1]、[2,4]、[3,3] → 总代价 2
代码:
代码解析
状态定义:
f[i][j] = 前 i 个数字分成 j 段的最小总代价
初始化:
f[0][0] = 0,其余为无穷大
转移方程:
f[i][j] = min(f[i][j], f[k][j-1] + 区间代价(k+1 ~ i))
区间代价 = 区间最大值 * 长度 - 区间和
实现细节:
1. 逆序枚举 k,顺便维护区间最大值 mx
2. 前缀和 s[i] 快速求区间和
3. 答案取 f[n][0...m+1] 的最小值