混合三种背包问题

混合背包问题(三种背包问题的总结) 有N种物品和一个容量是V的背包。 物品一共有三类: 第一类物品只能用1次(01背包); 第二类物品可以用无限次(完全背包); 第三类物品最多只能用si次(多重背包); 每种体积是vi,价值是wi。 求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。 输出最大价值。 输入格式 第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。 接下... 阅读详情

问题
如果将01背包、完全背包、多重背包混合起来。也就是说,有的物品只可以取一次(01背包),有的物品可以取无限次(完全背包),有的物品可以取的次数有一个上限(多重背包)。应该怎么求解呢?

01背包与完全背包的混合
考虑到在01背包和完全背包中最后给出的伪代码只有一处不同,故如果只有两类物品:一类物品只能取一次,另一类物品可以取无限次,那么只需在对每个物品应用转移方程时,根据物品的类别选用顺序或逆序的循环即可,复杂度是O(VN)。伪代码如下:

for i=1..N
    if 第i件物品是01背包
        for v=V..0
            f[v]=max{f[v],f[v-c[i]]+w[i]};
    else if 第i件物品是完全背包
        for v=0..V
            f[v]=max{f[v],f[v-c[i]]+w[i]};

再加上多重背包
如果再加上有的物品最多可以取有限次,那么原则上也可以给出O(VN)的解法:遇到多重背包类型的物品用单调队列解即可。但如果不考虑超过NOIP范围的算法的话,用多重背包中将每个这类物品分成O(log n[i])个01背包的物品的方法也已经很优了。

 cin>>x>>y>>s;         
while (s>=t){            
weight[++n1]=x*t;            
value[n1]=y*t;             
s-=t;            
t*=2;        
}        
weight[++n1]=x*s;        
value[n1]=y*s;  //把s以2的指数分堆:1,2,4,…,2^(k-1),s-2^k+1,

小结
有人说,困难的题目都是由简单的题目叠加而来的。这句话是否公理暂且存之不论,但它在本讲中已经得到了充分的体现。本来01背包、完全背包、多重背包都不是什么难题,但将它们简单地组合起来以后就得到了这样一道一定能吓倒不少人的题目。但只要基础扎实,领会三种基本背包问题的思想,就可以做到把困难的题目拆分成简单的题目来解决

旅行者有一个容量为V公斤的背包

 

n :物品种数

w :物品重量

c :物品价值

p :物品可以拿取的数目(0表示可取无穷多件)

 

输入样例:

10 3

2 1 0

3 3 1

4 5 4

 

输出样例:

11

//完全背包,同种物件多次拿取

for(int j=w[i];j<=m;j++)//从小到大的叠加多次选择
                f[j]=max( f[j],f[j-w[i]]+c[i] );

 for(int j=1;j<=p[i];j++)     //01背包和多重背包,拿的次数
            
                for(int k=m;k>=w[i];k--)//从大到小的空间的每次选一个,从后面值结合现值选出最大值
                    f[k]=max( f[k],f[k-w[i]]+c[i] );

 

多重背包 变 01背包,完全背包不变

#include<cstdio>
#include<iostream>
using namespace std;
int m,n;
int w[31],c[31],p[31];
int f[201];

int max(int x,int y)
{
    if(x<y)
        return y;
    else
        return x;

}

int main()
{
    scanf("%d%d",&m,&n);
    int n1=0;
    int x,y,s;
    for(int i=1; i<=n; i++)//都变成了01背包问题和完全背包问题
    {
        cin>>x>>y>>s;
        if(s>1)
        {
            int t=1;

            while (s>=t)
            {
                w[++n1]=x*t;
                c[n1]=y*t;
                p[n1]=1;

                s-=t;
                t*=2;
            }
            w[++n1]=x*s;
            c[n1]=y*s;
            p[n1]=1;
        }
        else
        {
            w[++n1]=x;
            c[n1]=y;
            p[n1]=s;
        }
    }

    for(int i=1; i<=n1; i++)
    {
        if(p[i]==0)     //完全背包
        {
            for(int j=w[i]; j<=m; j++) //从小到大的叠加多次选择
                f[j]=max( f[j],f[j-w[i]]+c[i] );
        }
        else //01背包
        {
            //for(int j=1; j<=p[i]; j++)   //多重背包
                for(int k=m; k>=w[i]; k--) //从大到小的逐一选择,从后面值结合现值选出最大值
                    f[k]=max( f[k],f[k-w[i]]+c[i] );
        }

    }
    for(int i=1; i<=m; i++)
    printf("%d\n",f[i]);
    printf("%d",f[m]);
    return 0;
}


 

#include<cstdio>
#include<iostream>
using namespace std;
int m,n;
int w[31],c[31],p[31];
int f[201];

int max(int x,int y)
{
    if(x<y)return y;
    else return x;

}

int main(){
    scanf("%d%d",&m,&n);
    
    for(int i=1;i<=n;i++)
        scanf("%d%d%d",&w[i],&c[i],&p[i]);

 

    for(int i=1;i<=n;i++){
        if(p[i]==0)     //完全背包
        {
            for(int j=w[i];j<=m;j++)//从小到大的叠加多次选择
                f[j]=max( f[j],f[j-w[i]]+c[i] );
        }
        else
        {    
            for(int j=1;j<=p[i];j++)     //01背包和多重背包
            
                for(int k=m;k>=w[i];k--)//从大到小的逐一选择,从后面值结合现值选出最大值
                    f[k]=max( f[k],f[k-w[i]]+c[i] );

        }
    }
    printf("%d",f[m]);
    return 0;
}

 

混合三种背包问题c++ 混合三种背包问题c++,你值得拥有【x 阅读详情

相关推荐

DMA学习笔记

DMA(direct memory access,直接内存访问),是一种避开CPU,可以直接对外设和内存进行访问的技术,可以实现外设与内存、内存之间、外设之间的数据的访问和搬移。

weixin_46220498的博客 3111

混合背包三类问题

背包1. 简单背包   背包问题不考虑空隙,只要物体体积之和不大于背包容量,就能放进去。 1. 简单背包   问题:背包容量 cap 已知,n 个各不相同的物体的体积 caps 已知,求有多少种方法正好把背包放满。 int dp[50][50]; template<int N> int simple_package(const int cap, const int(&caps)[N]) { dp[0][0] = 1; for (int i = 1; i <= cap; i++

sinoai 848

先进半导体材料与器件Chapter3

Chapter3 异质结双极晶体管(HBT) 作者:毛茏玮 / Saint 掘金:https://juejin.im/user/5aa1f89b6fb9a028bb18966a 微博:https://weibo.com/5458277467/profile?topnav=1&wvr=6&is_all=1 GitHub:github.com/saint-000 知乎:https:/...

一个会写代码的烤鸭 5801

DP复习——混合三种背包

混合三种背包 混合三种背包就是混合了01背包,完全背包,多重背包三种背包的问题。也就是说每种物品有的只能取一次,有的能取多次,有的数量充足。 解法 这类题目其实很简单。 01背包和多重背包可以一起化为一个01背包做。至于完全背包,只要判断一下内循环的枚举方向就行了。 伪代码 for(1..n) if(第i种物品是完全背包) for(w[i]..v) ...

蒟蒻柴犬首相的博客 408

Colmap参数调优实战:如何通过5个关键设置提升3D重建精度

本文深入探讨Colmap参数调优实战,通过5个关键设置显著提升3D重建精度。重点解析特征匹配参数、BA优化配置、初始化策略、资源分配及动态调整方法,结合量化数据和实际案例,帮助开发者精准优化重建流程,适用于古建筑扫描、无人机航拍等多种场景。

weixin_30872157的博客 430

别再只盯着报点率了:聊聊电容触摸屏算法里那些不为人知的‘软实力’

本文深入探讨了电容触摸屏算法中常被忽视的‘软实力’,包括环境噪声干扰、信号衰减补偿和多物理场耦合等核心挑战。通过对比消费电子与工业场景的算法需求,揭示了触摸算法在不同应用中的技术分野。文章还提供了实用的算法评估方法和前沿发展趋势,帮助开发者全面了解电容触摸屏技术的隐秘战场。

weixin_42524276的博客 388

背包问题(5):混合背包

混合背包就是将前面三种基本的背包问题叠加成较复杂的问题。也就是说,有的物品只可以取一次(0/1背包),有的物品可以取无限次(完全背包),有的物品可以取的次数有一个上限(多重背包)。 0/1背包与完全背包的混合比较简单。如果只有两类物品:一类物品只能取一次,另一类物品可以取无限次,那么只需在对每个物品应用转移方程时,根据物品的类别选用逆序(0/1背包)或顺序(完全背包)的循环即可。 一般可以编写如下的循环。​ for (i=1;i<=N;i++) ...

cmdos的专栏 2778

Fiddler everywhere的一些基础操作

网上能搜到的Fiddler everywhere使用教程太少,于是我整理了一些自己实操成功的内容,包括Fiddler everywhere的Mock测试、弱网测试等基础操作,后续还会持续更新。操作系统:macOS使用工具:Fiddler everywhere 5.10.0本文简单介绍了使用Fiddler everywhere进行的Mock测试和弱网测试,而Fiddler everywhere提供了更多的其他实用的功能,我会在后期进行一个持续的学习和更新。

weixin_44346646的博客 2478

混合背包(信息学奥数一本通-T1270)

【题目描述】 一个旅行者有一个最多能装V公斤的背包,现在有n件物品,它们的重量分别是W1,W2,...,Wn,它们的价值分别为C1,C2,...,Cn。有的物品只可以取一次(01背包),有的物品可以取无限次(完全背包),有的物品可以取的次数有一个上限(多重背包)。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。 【输入】 第一行:二个整数,M(背包容量,M≤200...

Alex_McAvoy的博客 2335

433MHz无线通信避坑指南:如何解决信号干扰和误码问题

本文深入探讨433MHz无线通信中的信号干扰和误码问题,提供从射频前端设计到协议优化的全链路解决方案。通过天线匹配、电源噪声抑制、曼彻斯特编码改进及实时频点切换等技术,显著提升通信稳定性和距离。适合智能家居和工业无线控制系统的开发者参考。

weixin_29288313的博客 415

告别偏移地址!用C# S7PLUS驱动读写西门子S7-1500符号地址(TIA Portal V17+环境配置)

本文详细介绍了如何在TIA Portal V17+环境中使用C# S7PLUS驱动读写西门子S7-1500 PLC的符号地址,告别传统的偏移地址方式。通过配置OpenSSL、集成S7PLUS驱动库,以及实战案例展示符号地址的读写方法,显著提升代码可读性和维护效率。文章还涵盖了环境准备、高级配置及常见问题解决方案,助力工业自动化开发者实现更高效的PLC通讯。

weixin_28720767的博客 315

混合三种背包问题,小白也可以看懂,哦耶~

多重背包问题 思路: 1.如果s[i] == 0,这件物品可以使用无限次——可以转化成多重背包问题 多重背包问题 2.如果是s[i] == -1,这件物品只能使用一次——可以转化为0-1背包问题 0-1背包 3.其它情况是每个物品给了确定的个数——可以转化成完全背包问题 完全背包问题 public class Main { int N; //物品的种数为N int V; //背包的容量为V public int mixBag(int[] v, int[] w, int[]

AnitaSun的博客 374

ResNet改进(20):融合Swin Transformer与ResNet

这种混合架构的设计理念是:在保留CNN强大局部特征提取能力的同时,引入Transformer的全局建模优势。我们实现的模型在ResNet18的基础上嵌入了一个简化版的Swin Transformer Block,旨在探索两种范式结合的可能性。通过在ResNet早期阶段引入Transformer模块,我们既保留了CNN强大的局部特征提取能力,又获得了Transformer的全局建模优势。本文提出的ResNet与Swin Transformer混合架构,探索了CNN与Transformer结合的可能性。

2401_82355416的博客 858

四、混合三种背包问题

如果将01背包、完全背包和多重背包混合起来,也就是说有的物品只可以取一次(01背包),有的物品可以取无限次(完全背包),有的物品取的次数有一个上限(多重背包)。这就是混合三种背包的背包问题。

Song331的博客 687

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

P04: 混合三种背包问题

P04: 混合三种背包问题 问题 如果将P01、P02、P03混合起来。也就是说,有的物品只可以取一次(01背包),有的物品可以取无限次(完全背包),有的物品可以取的次数有一个上限(多重背包)。应该怎么求解呢? 01背包与完全背包的混合 考虑到在P01和P02中给出的伪代码只有一处不同,故如果只有两类物品:一类物品只能取一次,另一类物品可以取无限次,那么只需在对每个物品应用转移方程时,根据

wenlovingliu的专栏 501

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

第四讲 混合三种背包问题

问题 如果将P01、P02、P03混合起来。也就是说,有的物品只可以取一次(01背包),有的物品可以取无限次(完全背包),有的物品可以取的次数有一个上限(多重背包)。应该怎么求解呢? 01背包与完全背包的混合 考虑到在P01和P02中给出的伪代码只有一处不同,故如果只有两类物品:一类物品只能取一次,另一类物品可以取无限次,那么只需在对每个物品应用转移方程时,根据物品的类别选用顺序或逆序的循环...

lannister_awalys_pay的博客 216

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

01背包、完全背包、多重背包、混合三种背包问题

01背包、完全背包、多重背包、混合三种背包问题 P01: 01背包问题 题目 有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。 基本思路 这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。 用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是:

616

混合三种背包问题(背包九讲)

问题:     如果将P01、P02、P03混合起来。也就是说,有的物品只可以取一次(01背包),有的物品可以取无限次(完全背包),有的物品可以取的次数有一个上限(多重背包)。应该怎么求解呢? 01背包与完全背包的混合:     考虑到在P01和P02中给出的伪代码只有一处不同,故如果只有两类物品:一类物品只能取一次,另一类物品可以取无限次,那么只需在对每个物品应用转移方程时,根据物品的类别

young TO challenge! 1624
上一篇: 求最大公约数的高效率算法
下一篇: DP复习——二维费用的背包
while_black
博客等级 码龄9年 25粉丝 57原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值