Acwing 7. 混合背包问题

Acwing 7. 混合背包问题

N 种物品和一个容量是 V 的背包。

物品一共有三类:

  • 第一类物品只能用 1 次(01背包);
  • 第二类物品可以用无限次(完全背包);
  • 第三类物品最多只能用 si 次(多重背包);

每种体积是 vi,价值是 wi

求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。

思路:

根据上文对这三个背包问题的了解,列出他们各自的转移方程

  • 01: f[i,j]=max(f[i1][j],f[iv[i]]+w[i])

  • 多重: f[i,j]=max(f[i1][j],f[i1,jv[i]],+,...,f[i1,jSiv[i]]+Siw[i])

  • 完全:f[i,j]=max(f[i1][j],f[i1,jv[i]],+,...,f[i1,jSv[i]]+Sw[i])

可知,当前物品的选法,和相应的更新值,和之前的物品类型无关。所以每次判断当前物品的类型,选择对应的转移方程来进行转移就可以了。

通过分析时间复杂度可知,多重背包需要用到二进制优化。

实现:

#include <stdio.h> #include <algorithm> using namespace std; const int N = 1005; int dp[N], n, m; struct Good { int w, v; } good[N]; int main() { scanf("%d%d", &n, &m); // 遍历物品 while (n--) { int v, w, s; scanf("%d%d%d", &v, &w, &s); // 如果可以无数次用,就是完全背包 if (!s) // 遍历体积 for (int j = v; j <= m; j++) dp[j] = max(dp[j], dp[j - v] + w); else { // 将01背包看成可以使用1次的多重背包 if (s == -1) s = 1; // 二进制优化多重背包看成01背包 int cnt = 1; for (int i = 1; i <= s; i *= 2) { good[cnt].v = v * i; good[cnt++].w = w * i; s -= i; } // 最后一部分 if (s > 0) { good[cnt].v = v * s; good[cnt++].w = w * s; } // 遍历物品 for (int i = 1; i < cnt; i++) // 遍历体积 for (int j = m; j >= good[i].v; j--) dp[j] = max(dp[j], dp[j - good[i].v] + good[i].w); } } printf("%d\n", dp[m]); return 0; }

__EOF__

本文作者zxr
本文链接https://www.cnblogs.com/zxr000/p/16999868.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zxr000  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示