背包问题(01背包、完全背包、多重背包)详解(超详细!!!),及题目代码和题意,包含6个例题。

第一题:01背包问题

01背包问题

时间限制:1秒        内存限制:128M

题目描述

一个旅行者有一个最多能装 M 公斤的背包,现在有 n 件物品,它们的重量分别是 W1,W2,...,Wn ,它们的价值分别为 C1 , C2 ,..., Cn ,求旅行者能获得最大总价值。

输入描述

第一行:两个整数,M (背包容量,M≤200 )和 N (物品数量, N≤30 );
第 2..N+1 行:每行二个整数 Wi,Ci ,表示每个物品的重量和价值。

输出描述

仅一行,一个数,表示最大总价值。

样例

输入

10 4
2 1
3 3
4 5
7 9

输出

12

重要信息筛选

最多能装 M 公斤的背包,现在有 n 件物品,它们的重量分别是 W1,W2,...,Wn ,它们的价值分别为 C1 , C2 ,..., Cn ,求最大总价值

思路:

对于每个物品有两个选择,放入或者不放,有 n 个物品,所以要做出 n 个选择,可以视为 n个状态阶段。
用 f[n][m]表示有 n 个物品时,放入容量为 m 的背包所能获得的最大价值。样例要求的就是 f[4][10]。
包容量为 10,考虑第 4 个物品(重量为 2,价值为 1),分两种情况:
1)放入第 4 个物品
对应的背包价值为前 3 个物品放在容量为(10-2)的包里的最大价值+第 4 个物品的价值。
f[4][10]=f[3][10-2]+1=f[3][8]+1
f[3][8]代表什么含义呢?
 -有前 3 个物品时,放入容量为 8 的背包所能获得的最大价值
 -考虑第 3 个物品,同样分为两种情况
a.f[3][8]=f[2][4]+5
b.f[3][8]=f[2][8]
2)不放入第 4 个物品
对应的背包价值和前 3 个物品放在容量为 10 的包里的价值一样。 f[4][10]=f[3][10]
1 和 2 两种情况哪个的背包价值更大,f[4][10]就是哪个值。


用 f[i][j]表示背包中有 i 个物品,重量为 j 时的价值情况,如下图所示:


以 f[2][8]为例, f[2][8]=max(f[1][8-3]+3,f[1][8])
 = max(f[1][5]+3,f[1][8])


求 f[2][8]的值时,只需要知道 f[1][8]左侧部分的数据即可。

其实把它优化成一维的,也是可行的,因为不用i-1,直接每次求最大值。此时状态转移方程变成这样:

此时,代码主体框架已经完成,完成输入输出即可

AC代码:

#include<bits/stdc++.h>
using namespace std;
int dp[10000005],w[10005],c[10005];//定义 
int main(){int n,m,cnt=0;scanf("%d%d",&m,&n);//输入最大容量和数量 for(int i=1; i<=n; i++){cin>>w[i]>>c[i];//输入重量和 }for(int i=1;i<=n;i++){//枚举所有物品for(int j=m;j>=w[i];j--){//枚举从最大容量到当前物品重量dp[j]=max(dp[j],dp[j-w[i]]+c[i]);//dp[当前容量]=max(dp[当前容量],dp[当前容量-当前物品重量]+当前物品价值);}}printf("%d",dp[m]);//输出 return 0;
}

第二题:采药

采药

时间限制:1秒        内存限制:128M

题目描述

辰辰是个很有潜能、天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。

如果你是辰辰,你能完成这个任务吗?

输入描述

输入的第一行有两个整数T(1≤T≤1000)和M(1≤M≤100),T代表总共能够用来采药的时间,M代表山洞里的草药的数目。接下来的M行每行包括两个在1到100之间(包括1和100)的的整数,分别表示采摘某株草药的时间和这株草药的价值。

输出描述

输出只包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。

样例

输入

70 3
71 100
69 1
1 2

输出

3

思路:

转化为T为背包容量M为物品数量采药时间看成重量采药价值看成价值,再套用01背包完成此问题

 对于每个物品有两个选择,放入或者不放,有 n 个物品,所以要做出 n 个选择,可以视为 n个状态阶段。
用 f[n][m]表示有 n 个物品时,放入容量为 m 的背包所能获得的最大价值。样例要求的就是 f[4][10]。
包容量为 10,考虑第 4 个物品(重量为 2,价值为 1),分两种情况:
1)放入第 4 个物品
对应的背包价值为前 3 个物品放在容量为(10-2)的包里的最大价值+第 4 个物品的价值。
f[4][10]=f[3][10-2]+1=f[3][8]+1
f[3][8]代表什么含义呢?
 -有前 3 个物品时,放入容量为 8 的背包所能获得的最大价值
 -考虑第 3 个物品,同样分为两种情况
a.f[3][8]=f[2][4]+5
b.f[3][8]=f[2][8]
2)不放入第 4 个物品
对应的背包价值和前 3 个物品放在容量为 10 的包里的价值一样。 f[4][10]=f[3][10]
1 和 2 两种情况哪个的背包价值更大,f[4][10]就是哪个值。


用 f[i][j]表示背包中有 i 个物品,重量为 j 时的价值情况,如下图所示:


以 f[2][8]为例, f[2][8]=max(f[1][8-3]+3,f[1][8])
 = max(f[1][5]+3,f[1][8])


求 f[2][8]的值时,只需要知道 f[1][8]左侧部分的数据即可。

其实把它优化成一维的,也是可行的,因为不用i-1,直接每次求最大值。此时状态转移方程变成这样:

此时,代码主体框架已经完成,完成输入输出即可

AC代码:

#include<bits/stdc++.h>
using namespace std;
int dp[10000005],w[10005],c[10005];//定义 
int main(){int n,m,cnt=0;scanf("%d%d",&m,&n);//输入最大容量和数量 for(int i=1; i<=n; i++){cin>>w[i]>>c[i];//输入重量和 }for(int i=1;i<=n;i++){//枚举所有物品for(int j=m;j>=w[i];j--){//枚举从最大容量到当前物品重量dp[j]=max(dp[j],dp[j-w[i]]+c[i]);//dp[当前容量]=max(dp[当前容量],dp[当前容量-当前物品重量]+当前物品价值);}}printf("%d",dp[m]);//输出 return 0;
}

第三题:数字组合

数字组合

时间限制:1秒        内存限制:128M

题目描述

在N个数中找出其和为M的若干个数。先读入正整数N(1< N< 100)和M(1< M< 10000),再读入N个正数(可以有相同的数字,每个数字均在1000以内),在这N个数中找出若干个数,使它们的和是M,把满足条件的数字组合都找出来以统计组合的个数,输出组合的个数(不考虑组合是否相同)。要求你的程序运行时间不超过1秒。

输入描述

第一行是两个数字,表示N和M。 第二行起是N个数。

输出描述

就一个数字,表示和为M的组合的个数。

样例

输入

4 4
1 1 2 2

输出

3

思路:

这是典型的 0/1 背包模型,n 个正整数就是 n 个物品,t 就是背包的容积。
在外层循环到 i 时(表示从前 i 个数中选),设 f[j]表示“和为 j”有多少种方案。在具体实现中,只需要把上面代码中求 max 的函数改为求和即可。

这边为大家奉上代码

#include<bits/stdc++.h>
using namespace std;
int main(){int n,m,a[10005],f[10005];cin>>n>>m;for(int i=1; i<=n; i++) cin>>a[i];f[0]=1;for(int i=1; i<=n; i++){for(int j=m; j>=a[i]; --j){f[j]+=f[j-a[i]];}}cout<<f[m]<<endl;return 0;
}

第四题:完全背包问题

完全背包问题

时间限制:1秒        内存限制:128M

题目描述

设有n种物品,每种物品有一个重量及一个价值。但每种物品的数量是无限的,同时有一个背包,最大载重量为M,今从n种物品中选取若干件(同一种物品可以多次选取),使其重量的和小于等于M,而价值的和为最大。

输入描述

第一行:两个整数,M(背包容量,M≤200)和N(物品数量,N≤30); 

第2..N+1行:每行二个整数Wi,Ci,表示每个物品的重量和价值。

输出描述

仅一行,一个数,表示最大总价值。

样例

输入

10 4
2 1
3 3
4 5
7 9

输出

max=12

思路:

状态为 f[x],表示包容量为 x 时获得的最大价值
放入的最后一个物品可能是重量小于 x 的任何一个,选最大的那个
f[12],包容量为 12 时获得的最大价值
只考虑最后一个物品,分四种情况
1)最后一个是物品①(重量为 2,价值为 1)
f[12]=f[12-2]+1=f[10]+1
2)最后一个是物品②(重量为 3,价值为 3)
f[12]=f[12-3]+3=f[9]+3
3)最后一个是物品③(重量为 4,价值为 5)
f[12]=f[12-4]+5=f[8]+5
4)最后一个是物品④(重量为 7,价值为 9)
f[12]=f[12-7]+9=f[5]+9
找四种情况里最大的那个
f[5],包容量为 5 时获得的最大价值
只考虑最后一个物品,分三种情况
1)最后一个是物品①(重量为 2,价值为 1)
f[5]=f[5-2]+1=f[3]+1
2)最后一个是物品②(重量为 3,价值为 3)
f[5]=f[5-3]+3=f[2]+3
3)最后一个是物品③(重量为 4,价值为 5)
f[5]=f[5-4]+5=f[1]+5
4)最后一个可能是物品④(重量为 7,价值为 9)吗?

所以,根据思路,即可写出代码:

#include<bits/stdc++.h>
using namespace std;
int f[10000005],w[10005],c[10005];
int main(){int n,m,cnt=0;scanf("%d%d",&m,&n);for(int i=1; i<=n; i++){cin>>w[i]>>c[i];}for(int i=1;i<=n;i++){for(int j=w[i];j<=m;j++){//01背包是从m到w[i],完全背包是w[i]到mf[j]=max(f[j],f[j-w[i]]+c[i]);}}printf("max=%d",f[m]);return 0;
}

第五题:多重背包

多重背包

时间限制:1秒        内存限制:128M

题目描述

现有N种(N<=10)魔法石和一个容量为V(0<V<200)的背包。第i种魔法石最多有n[i]件可用,每个占用的空间是c[i],价值是w[i]。全部物品总数不超过50.求解将哪些魔法石装入背包可使这些物品的容量总和不超过背包容量,且价值总和最大

输入描述

第一行为两个数字,即V和N。以下N行为每种物品的空间,价值和数量

输出描述

最大价值总和

样例

输入

8 2
2 100 4
4 100 2

输出

400

对于每个物品有 ?个选择
用 f[n][m]表示有 n 个物品时,放入容量为 m 的背包所能获得的最大价值。样例要求的就是 f[2][8]。
包容量为 8,考虑物品②(空间为 4,价值为 100,总量为 2),分 3 种情况1)放入 0 个物品②
f[2][8]=f[1][8]
2)放入 1 个物品②
f[2][8]=f[1][8-4]+100=f[1][4]+100
2)放入 2 个物品②
f[2][8]=f[1][8-4*2]+100*2=f[1][0]+200


3 种情况哪个的背包价值更大,f[2][8]就是哪个值。

也可以用一维数组进行优化
程序:

#include<bits/stdc++.h>
using namespace std;
int f[40005];
int main(){int n,m;scanf("%d%d",&n,&m);int c[2005],w[2005],s[2005];for(int i=1; i<=n; i++){scanf("%d%d%d",w+i,c+i,s+i);}for(int i=1;i<=n;i++){for(int k=1;k<=s[i];k++){   for(int j=m;j>=w[i];j--){f[j]=max(f[j],f[j-w[i]]+c[i]);}}} printf("%d",f[m]);return 0;
}

第六题:买书

买书

时间限制:1秒        内存限制:128M

题目描述

小明手里有n元钱全部用来买书,书的价格为10元,20元,50元,100元。 

问小明有多少种买书方案?(每种书可购买多本)

输入描述

一个整数 n,代表总共钱数。(0 <= n <= 1000)

输出描述

一个整数,代表选择方案种数

样例

输入

20

输出

2

题目分析:


现在有四种类型的书,可以类比成四种物品,重量就是书的价格,可以用完全背包的方法来
求解,但是本题目不是求最大价值,而是求方案数。完全背包问题求解方案数把 max 修改成 sum 就可以了
f[i][j]表示前 i 件物品放到背包容量为 j 的背包的方案数
状态转移方程:
f[i][j] += f[i-1][j-w[i]]

初始化为:f[0][0] = 1
也可以用一维优化
f[i]表示放到背包容量为 i 的背包里面总共有多少种方案
状态转移方程:
f[j] += f[j - a[i]];

代码:

#include<bits/stdc++.h>
using namespace std;
int a[]={0,10,20,50,100};
int f[20000005];
int main(){int n;cin>>n;f[0]=1;for(int i=1; i<=4; i++){for(int j=a[i]; j<=n; ++j){f[j]+=f[j-a[i]];}}cout<<f[n]<<endl;return 0;
}

总结:背包问题真难啊

往期回顾:

可达鸭二月月赛——入门赛第四场T1题解

可达鸭二月月赛——入门赛第四场T2题解

可达鸭二月月赛——入门赛第四场T3题解

可达鸭二月月赛——入门赛第四场T4题解

可达鸭二月月赛——入门赛第四场(周三)题解

点个赞吧,求求了,制作不易。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/673967.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FXTM富拓监管变更!2024开年连续3家交易商注销牌照

交易商的监管信息是经常发生变更的&#xff0c;即使第一次投资时查询平台监管牌照&#xff0c;投资者仍需持续关注其监管动态。千万不要以为第一步审核好后就万事大吉了&#xff01; 2024年开年&#xff0c;就有3家交易商的重要信息发生变更&#xff0c;注销其金融监管牌照&…

专业课147总420+福州大学866信号与系统考研经验福大电子信息技术信息与通信

我本人一战双非上岸福大&#xff0c;初试分数420&#xff0c;期中专业课866信号与系统147&#xff08;有点遗憾没有达到信息通信考研Jenny老师辅导班要求的满分&#xff09;。这里想分享一些自己准备初试的过程和一些学习方法&#xff0c;希望能给各位准备报考福州大学866的学弟…

HiveSQL——借助聚合函数与case when行转列

一、条件函数 if 条件函数 if函数是最常用到的条件函数&#xff0c;其写法是if(xn,a,b), xn代表判断条件&#xff0c;如果xn时&#xff0c;那么结果返回a ,否则返回b。 selectif(age < 25 or age is null, 25岁以下, 25岁以上) as age_cnt,count(1) as number from table…

WifiConfigStore初始化读取-Android13

WifiConfigStore初始化读取 1、StoreData创建并注册2、WifiConfigStore读取2.1 文件读取流程2.2 时序图2.3 日志 1、StoreData创建并注册 packages/modules/Wifi/service/java/com/android/server/wifi/WifiConfigManager.java mWifiConfigStore.registerStoreData(mNetworkL…

读千脑智能笔记07_人工智能的未来(中)

1. 机器智能的未来 1.1. 没有任何技术原因阻止我们创造智能机器 1.1.1. 障碍在于我们缺乏对智能的理解&#xff0c;也不知道产生智能所需的机制 1.2. 历史表明&#xff0c;我们无法预测将推动机器智能向前发展的技术进步 1.2.1. …

pytorch训练指标记录之tensoboard,wandb

详解Tensorboard及使用教程_tensorboard怎么用-CSDN博客文章浏览阅读5.1w次&#xff0c;点赞109次&#xff0c;收藏456次。目录一、什么是Tensorboard二、配置Tensorboard环境要求安装三、Tensorboard的使用使用各种add方法记录数据单条曲线(scalar)多条曲线(scalars)直方图(hi…

使用frp时遇到的问题connect: connection refuseddial tcp xxxx:7000: connect: connection refused

最近在做的项目需要用到frp来做代理连接本地内网机&#xff0c;卡在最后启动客户端的时候&#xff0c;提示报错&#xff1a;login to server failed: dial tcp xxxx:7000: connect: connection refuseddial tcp xxxx:7000: connect: connection refused&#xff01;&#xff01…

功能强大的国外商业PHP在线教育系统LMS源码,直播课程系统

源码介绍 Proacademy是在线教育一体化的解决方案&#xff0c;用于创建类似于Udemy、Skillshare、Coursera这种在线教育市场。 这个平台提供在线课程&#xff0c;现场课程&#xff0c;测验等等&#xff0c;并有一个基于实际业务需要的高级认证插件&#xff0c;程序基于Laravel…

BeginCTF2024 RE 部分复现

8. arc 上面一托混淆&#xff0c;左边似乎是三个东西相乘 单独取出最左边一托打印&#xff0c;可以得到大数组 接下来要解密&#xff0c;原代码非常混乱&#xff0c;我们先整理一下&#xff0c;简单去混淆 print (all([[data][a][d] e for a, b in enumerate([[int(a) for a …

MOS管防反接电路设计

电子元件大都是使用直流工作&#xff0c;电源线反接就有可能就会烧坏&#xff0c;那电路如何防反接&#xff1f;首当其冲我们想到的就是二极管了&#xff0c;运用其单向导通特性可有效防止电源反接而损坏电路&#xff0c;但是随之而来的问题是二极管存在PN节电压&#xff0c;通…

PyTorch 2.2大更新!集成FlashAttention-2,性能提升2倍

【新智元导读】新的一年&#xff0c;PyTorch也迎来了重大更新&#xff0c;PyTorch 2.2集成了FlashAttention-2和AOTInductor等新特性&#xff0c;计算性能翻倍。 新的一年&#xff0c;PyTorch也迎来了重大更新&#xff01; 继去年十月份的PyTorch大会发布了2.1版本之后&#…

如何获取和查找您的Android设备的序列号

Hello大家好&#xff01;我是咕噜铁蛋&#xff01;&#xff0c;我们经常会在文章中提及到各种各样的Android设备&#xff0c;而其中一个重要的标识就是设备的序列号。设备的序列号在很多情况下被用于唯一标识一个设备&#xff0c;例如在软件开发中进行设备的调试和测试&#xf…

Redis篇之分布式锁

一、为什么要使用分布式锁 1.抢劵场景 &#xff08;1&#xff09;代码及流程图 &#xff08;2&#xff09;抢劵执行的正常流程 就是正好线程1执行完整个操作&#xff0c;线程2再执行。 &#xff08;3&#xff09;抢劵执行的非正常流程 因为线程是交替进行的&#xff0c;所以有…

C 语言学习七:指针

指针 指针与地址指针的声明和初始化指针的解引用指针的比较指针和数组指针数组指针和动态内存分配 指针与函数参数指针作为函数参数二级指针 指向函数的指针 指针与地址 指针的声明和初始化 int variable 42; int *ptr &variable; //间接访问 int value *ptr; // valu…

C# 实现微信自定义分享

目录 需求与调整 代码实现 获取令牌 生成合法票据 获取有效签名 客户端准备 客户端实现 小结 需求与调整 在微信中打开网页应用后&#xff0c;可以选择将地址发送给朋友进行分享&#xff0c;如下图&#xff1a; 在实际的应用中&#xff0c;我们可能不是简单的将该网页…

通过dockerfile 生成自定义nginx镜像

通过dockerfile生成自定义nginx镜像 &#xff01;&#xff01;&#xff01;docker 必须在linux环境下才能进行如果你是window则需要装虚拟机 新建一个文件名字为Dockerfile&#xff0c;无需后缀 文件完整名就是Dockerfile 编写dockerfile FROM nginx RUN echo hello nginx!…

Ubuntu Linux使用PL2302串口和minicom进行开发板调试

调试远程的服务器上面的BMC&#xff0c;服务器上面安装了Ubuntu&#xff0c;想着可以在服务器接个串口到BMC&#xff0c;然后SSH到服务器的Ubuntu&#xff0c;用minicom来查看串口信息。 准备&#xff1a; 服务器Ubuntu安装mimicom 本机可以ssh到Ubuntu 串口工具PL2302 或者CH3…

【数据分享】1929-2023年全球站点的逐年平均降水量(Shp\Excel\免费获取)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、湿度等指标&#xff0c;说到常用的降水数据&#xff0c;最详细的降水数据是具体到气象监测站点的降水数据&#xff01; 有关气象指标的监测站点数据&#xff0c;之前我们分享过1929-2023年全…

全局唯一id生成器 各种实现记录

全局唯一id生成器 Redis 生成 前提知识~~ 时间戳 时间戳这个东西我们老是听到,却可能不是特别了解 首先,时间戳是从1970年1月1号0点0分开始的秒数,我查了蛮多资料,理论上来说,时间戳是没有上限的,而我们一般用位数来限制这里的上限,比如32位 我们来实际计算一下 32位的二进…

巴尔加瓦算法图解:算法运用。

树 如果能将用户名插入到数组的正确位置就好了&#xff0c;这样就无需在插入后再排序。为此&#xff0c;有人设计了一种名为二叉查找树(binary search tree)的数据结构。 每个node的children 都不大于两个。对于其中的每个节点&#xff0c;左子节点的值都比它小&#xff0c;…