疯狂的背包问题(8) - 多重背包问题 I
多重背包模板题,数据范围很小(N,V,s≤100),直接三重循环 DP,每个物品枚举选取件数即可。
OJ: luogu
题目 ID: U661992
难度:普及-
标签:动态规划多重背包背包
日期: 2026-08-08 23:11
题意
有
思路
一句话本质:把每种物品的
最直接的做法是什么?
对每种物品枚举选取件数 brute.py 正是这样做的——DFS 枚举每种物品选几个,复杂度
既然选
可以。因为每件物品之间没有依赖关系——选第
这就得到了三重循环:
- 外层遍历每种物品
- 中层容量
从 倒序到 (01 背包要求倒序,防止同一轮中重复选取同一物品的多个"展平"副本) - 内层枚举选取件数
,更新
为什么容量循环必须倒序?
这和标准 01 背包完全一样。如果正序,已经更新过的
代码
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* 多重背包问题 I — N≤100 V≤100 s_i≤100,直接三重循环DP
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 105;
int n, V;
int dp[maxn];
int main() {
ios::sync_with_stdio(false); cin.tie(0);
cin >> n >> V;
for (int i = 1; i <= n; ++i) {
int v, w, s;
cin >> v >> w >> s;
for (int c = V; c >= 0; --c)
for (int k = 1; k <= s && k * v <= c; ++k)
dp[c] = max(dp[c], dp[c - k * v] + k * w);
}
cout << dp[V] << '\n';
return 0;
}复杂度
- 时间:
,最坏 ,轻松通过。 - 空间:
,滚动数组。
总结
多重背包最朴素的做法就是把每个物品拆成