当前位置: 首页 > news >正文

[DP]多重背包

多重背包

问题描述:给定 n n n种物品和一个体积为 V V V的背包,第 i i i种物品数量为 m i m_i mi,体积为 c i c_i ci,价值为 w i w_i wi。如何装填背包使总价值最大?

通过直接求解,转移方程式: d p [ i ] [ j ] = max ⁡ ( d p [ i − 1 ] [ j ] , d p [ i − 1 ] [ j − k × c [ i ] ] + k × w [ i ] ) , k ∈ [ 1 , min ⁡ ( m [ i ] , j c [ i ] ) ] dp[i][j]=\max(dp[i-1][j],dp[i-1][j-k\times c[i]]+k\times w[i]),k\in[1,\min(m[i],\frac{j}{c[i]})] dp[i][j]=max(dp[i1][j],dp[i1][jk×c[i]]+k×w[i]),k[1,min(m[i],c[i]j)]。复杂度 O ( V ∑ i = 1 n m i ) O(V\sum\limits_{i=1}^n m_i) O(Vi=1nmi),超时。

实际上,多重背包属于 0 / 1 0/1 0/1背包的推广,易得其可转换为 0 / 1 0/1 0/1背包问题:将第 i i i种物品视为 m i m_i mi种独立(不同)的物品,并按 0 / 1 0/1 0/1背包求解。定义状态数组 d p [ i ] [ j ] dp[i][j] dp[i][j],表示将前 i i i个物品放入容积为 j j j的背包时的最大价值。实际上复杂度不变,仍为 O ( V ∑ i = 1 n m i ) O(V\sum\limits_{i=1}^n m_i) O(Vi=1nmi),超时。

int dp[n+1][V+1],c[n],w[n],m[n];
int MultiplePack(){
    for(int i=0;i<=n;i++) dp[i][0]=0;
    for(int i=0;i<=V;i++) dp[0][i]=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=V;j++)
            for(int k=1;k<=m[i]&&k*c[i]<=j;k++)
                dp[i][j]=max(dp[i][j],dp[i-1][j-k*c[i]]+k*w[i]);
    return dp[n][V];
}

二进制优化

原理:倍增。任意十进制整数均可使用2的幂次经过有限次相加得到,以 2 i ( i ∈ [ 0 , ⌈ log ⁡ 2 m i ⌉ + 1 ] ) 2^i(i\in[0,\lceil\log_2m_i\rceil+1]) 2i(i[0,log2mi+1])顺次拆分,最后可能有一个余数。因此使用倍增即可将第 i i i种物品变为 log ⁡ 2 m i \log_2m_i log2mi个,每个物品体积为 2 k × c i 2^k\times c_i 2k×ci,价值为 2 k × w i 2^k\times w_i 2k×wi

以下为二进制拆分代码,之后使用new_nnew_cnew_w 0 / 1 0/1 0/1背包求解即可。复杂度 O ( V ∑ i = 1 n log ⁡ 2 m i ) O(V\sum\limits_{i=1}^n \log_2m_i) O(Vi=1nlog2mi)

int new_n=0,new_c[N],new_w[N];
for(int i=1;i<=n;i++){//遍历每种物品
    for(int j=1;j<=m[i];j<<=1){//遍历每种物品的个数
        new_n++;
        m[i]-=j;
        new_c[new_n]=j*c[i];
        new_w[new_n]=j*w[i];
    }
    if(m[i]){//若有余数
        new_n++;
        new_c[new_n]=m[i]*c[i];
        new_w[new_n]=m[i]*w[i];
    }
}

单调队列优化

相关文章:

  • 【征程 6】工具链 VP 示例中日志打印解读
  • LeetCode hot 100—删除链表的倒数第N个节点
  • 基于kotlin native的C与kotlin互相调用
  • 数值稳定性
  • Linux开发工具——make/makefile
  • 十大排序-20分钟完成
  • Redis-list类型
  • Spring常见问题复习
  • Web前端页面搭建
  • python logging模块
  • ACM代码模式笔记
  • 学透Spring Boot — 011. 一篇文章学会Spring Test
  • 操作系统——2.4 (管程与死锁的基本概念)
  • 第六章:分布式共识_《凤凰架构:构建可靠的大型分布式系统》
  • 解码 __iter__ 和 itertools.islice - 迭代的艺术
  • 数据结构(5)——栈
  • 【Python爬虫高级技巧】BeautifulSoup高级教程:数据抓取、性能调优、反爬策略,全方位提升爬虫技能!
  • cpp自学 day19(多态)
  • 一周学会Pandas2 Python数据处理与分析-NumPy数据类型
  • 【JavaWeb-Spring boot】学习笔记