--- title: "单调队列优化多重背包问题" created: 2025-11-28 tags: - 算法 --- # 单调队列优化多重背包问题 ## 题目描述 有 n(0 using namespace std; const int N = 1010, M = 20010; int n, m; int v[N], w[N], s[N]; int f[N][M]; int q[M]; int main() { cin >> n >> m; for (int i = 1; i <= n; ++ i) cin >> v[i] >> w[i] >> s[i]; for (int i = 1; i <= n; ++ i) { for (int r = 0; r < v[i]; ++ r) { int hh = 0, tt = -1; for (int j = r; j <= m; j += v[i]) { while (hh <= tt && j - q[hh] > s[i] * v[i]) hh ++ ; while (hh <= tt && f[i - 1][q[tt]] + (j - q[tt]) / v[i] * w[i] <= f[i - 1][j]) -- tt; q[ ++ tt] = j; f[i][j] = f[i - 1][q[hh]] + (j - q[hh]) / v[i] * w[i]; } } } cout << f[n][m] << endl; return 0; } ``` ### 一维优化 时间复杂度:O(n×v) 空间复杂度:O(v) 和 01背包 的优化类似,观察到 状态转移方程,对于 i 阶段,只会用到 i-1 层的状态 因此可以采用 拷贝数组 或 滚动数组 的写法 #### 拷贝数组写法 ```cpp #include #include using namespace std; const int N = 1010, M = 20010; int n, m; int v[N], w[N], s[N]; int f[M], g[M]; int q[M]; int main() { cin >> n >> m; for (int i = 1; i <= n; ++ i) cin >> v[i] >> w[i] >> s[i]; for (int i = 1; i <= n; ++ i) { memcpy(g, f, sizeof g); for (int r = 0; r < v[i]; ++ r) { int hh = 0, tt = -1; for (int j = r; j <= m; j += v[i]) { while (hh <= tt && j - q[hh] > s[i] * v[i]) hh ++ ; while (hh <= tt && g[q[tt]] + (j - q[tt]) / v[i] * w[i] <= g[j]) -- tt; q[ ++ tt] = j; f[j] = g[q[hh]] + (j - q[hh]) / v[i] * w[i]; } } } cout << f[m] << endl; return 0; } ``` #### 滚动数组写法 ```cpp #include using namespace std; const int N = 1010, M = 20010; int n, m; int v[N], w[N], s[N]; int f[2][M]; int q[M]; int main() { cin >> n >> m; for (int i = 1; i <= n; ++ i) cin >> v[i] >> w[i] >> s[i]; for (int i = 1; i <= n; ++ i) { for (int r = 0; r < v[i]; ++ r) { int hh = 0, tt = -1; for (int j = r; j <= m; j += v[i]) { while (hh <= tt && j - q[hh] > s[i] * v[i]) hh ++ ; while (hh <= tt && f[(i - 1) & 1][q[tt]] + (j - q[tt]) / v[i] * w[i] <= f[(i - 1) & 1][j]) -- tt; q[ ++ tt] = j; f[i & 1][j] = f[(i - 1) & 1][q[hh]] + (j - q[hh]) / v[i] * w[i]; } } } cout << f[n & 1][m] << endl; return 0; } ``` 作者:一只野生彩色铅笔 链接: [AcWing 6. 多重背包问题 III - AcWing](https://www.acwing.com/video/218/) 这个视频讲的不是很清楚 和那个快慢指针似的 胡过去 提高课有视频 等买了回过头来想这个问题 --- ⬅️ [[2-Learning/02-算法/03-刷题理模型/简单DP相关模型/背包问题/多重背包练习/最大价值|最大价值]] 🏠 [[00-刷题理模型]] ➡️ [[多重背包问题|多重背包问题]]