1 条题解
-
0
题解
本题使用动态规划求解分段装箱的最小代价问题。
算法思路:
-
状态定义:
dp[i]
:将前 个橙子装箱的最小代价- 每个箱子最多装 个橙子
- 每个箱子的代价为
-
转移方程:
- 枚举最后一个箱子的起始位置 (满足 )
- 计算区间 的最大值 和最小值
- 转移:$dp[i] = \min(dp[i], dp[j-1] + k + (mx - mn) \times (i - j + 1))$
-
优化策略:
- 在转移时同时维护区间 的最大值和最小值
- 从 向前枚举 ,动态更新 和
- 只需要枚举最近的 个位置
-
边界条件:
- (没有橙子时代价为 )
- 初始化
-
答案输出:
- 输出
时间复杂度:,对于每个位置 ,最多枚举 个起始位置。
这是一道经典的分段DP问题,关键在于理解状态转移和代价的计算方式。
#include <iostream> #define MAXN 20003 #define IMX 0x3f3f3f3f #define LMX 0x3f3f3f3f3f3f3f3fLL using namespace std; using lli = long long; int a[MAXN]; lli dp[MAXN]; int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); int n, m, k; cin >> n >> m >> k; for (int i = 1, mn, mx; i <= n; ++i) { cin >> a[i], mn = IMX, mx = -IMX, dp[i] = LMX; for (int j = i; j && i - j < m; --j) { mn = min(mn, a[j]), mx = max(mx, a[j]); dp[i] = min(dp[i], k + (lli)(mx - mn) * (i - j + 1) + dp[j - 1]); } } cout << dp[n]; return 0; }
-
- 1
信息
- ID
- 3476
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者