动态规划-背包DP

背包DP是线性DP中一种特殊的DP。

01背包

最基础的背包,有 n 件物品,背包容量为 V,每件物品只有一件。可以使用空间优化,一般是原地滚动,此时注意容量需要从后往前更新,否则会一个状态更新多次。时间复杂度为 O(nV)

核心代码

void solve() {
int n, V;
cin >> n >> V;
for (int i = 1; i <= n; i++) {
cin >> v[i] >> w[i];
}
for (int i = 1; i <= n; i++) {
for (int j = V; j >= v[i]; j--) { // 注意倒序更新
dp[j] = max(dp[j], dp[j - v[i]] + w[i]); // 体积均为j,取价值最大的
}
}
cout << dp[V] << "\n";
}

例题
装箱问题
01背包问题
开心的金明
采药

完全背包

n 件物品,背包容量为 V,每件物品有无穷件。可以使用空间优化,一般是原地滚动,与01背包恰好相反,此时容量从前往后更新即可。复杂度为 O(nV)

核心代码

void solve() {
int n, V;
cin >> n >> V;
for (int i = 1; i <= n; i++) {
cin >> v[i] >> w[i];
}
for (int i = 1; i <= n; i++) {
for (int j = v[i]; j <= V; j++) {
dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
}
}
cout << dp[V] << "\n";
}

例题
完全背包问题

分组背包

n 组物品,背包容量为 V,每组物品只能选一个。需要注意循环顺序,先对容量循环,再对每一组中的物品循环,因为每组中的物品相当于一组的一个状态,这些状态之间是互斥的。时间复杂度为 O(n×V)。

核心代码

void solve() {
int N, V, S;
cin >> N >> V;
vector<int> v[N + 1], w[N + 1], dp(V + 1);
for (int i = 1; i <= N; i++) {
cin >> S;
v[i].resize(S);
w[i].resize(S);
for (int j = 0; j < S; j++) {
cin >> v[i][j] >> w[i][j];
}
}
for (int i = 1; i <= N; i++) {
for (int j = V; j >= 0; j--) {
for (int k = 0; k < v[i].size(); k++) {
if (j >= v[i][k]) {
dp[j] = max(dp[j], dp[j - v[i][k]] + w[i][k]);
}
}
}
}
cout << dp[V] << "\n";
}

例题
分组背包问题
小红升装备
小红组比赛

多重背包

n 组物品,背包容量为 V,每组物品有有限个,其重量和价值相同。循环顺序为先对每一组中的物品循环,再对容量循环,若将多重背包中每组物品单独拿出来,可以看作01背包,而将物品进行组合可看作分组背包。时间复杂度为 O(n×V)。可对每组中物品的组合进行优化,降低时间复杂度。

核心代码

void solve() {
int N, V;
cin >> N >> V;
vector<int> v(N + 1), w(N + 1), s(N + 1), dp(V + 1);
for (int i = 1; i <= N; i++) {
cin >> v[i] >> w[i] >> s[i];
}
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= s[i]; j++) {
for (int k = V; k >= v[i]; k--) {
dp[k] = max(dp[k], dp[k - v[i]] + w[i]);
}
}
}
cout << dp[V] << "\n";
}

例题:
多重背包问题 I

posted @   catting123  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示