把摆件分层摆放 · 每层宽度 ≤ W · 求总高度最小值
有 n 个摆件,按顺序摆放在架子上。每个摆件 i 有宽度 wi 和高度 hi。
规则:
💡 本质:将序列切分成若干连续段,每段宽度和 ≤ W, 每段代价 = 段内最大高度,求总代价最小值。
假设有 5 个摆件,架子宽度 W = 10:
dp[i] = 前 i 个摆件(1 ~ i)的最小总高度。dp[n]
dp[i] = min( dp[j-1] + max(hj, ..., hi) )dp[0] = 0(没有摆件,高度为 0)max(h[j..i])(本层最高摆件)dp[i] = min(dp[j-1] + 层高),取所有合法 j 的最小值i = 1 → n,内层 j = i → 1 向左枚举sumW,超过 W 就 breakmaxH,随 j 左移更新dp[i] = min(dp[i], dp[j-1] + maxH)#include <vector> #include <algorithm> #include <climits> using namespace std; // 摆件结构体 struct Item { int w; // 宽度 int h; // 高度 }; // 计算架子最小总高度 int minShelfHeight(vector<Item>& items, int W) { int n = items.size(); vector<int> dp(n + 1, INT_MAX); dp[0] = 0; // 没有摆件时高度为 0 // 1‑based 索引,items[0] 对应摆件 1 for (int i = 1; i <= n; i++) { int sumW = 0; // 当前层累计宽度 int maxH = 0; // 当前层最大高度 // 从 i 向左枚举 j,尝试将 [j..i] 作为一层 for (int j = i; j >= 1; j--) { sumW += items[j - 1].w; // 累加宽度 if (sumW > W) break; // 超宽,停止 maxH = max(maxH, items[j - 1].h); // 更新层高 // dp[j-1] + 本层层高 → dp[i] dp[i] = min(dp[i], dp[j - 1] + maxH); } } return dp[n]; // 前 n 个摆件的最小总高度 }