动态规划——背包问题(01,完全,多重)

news2024/9/20 20:30:42

一、01背包问题

        1.题目描述

        有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。第 i 件物品的体积是 vi,价值是 wi。

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

         01背包问题特点:每个物品只能用一次,只能选择或者不选择

        2.动态规划思想

        动态规划就是需要解决子问题,再通过状态转移方程拓展至整体最优。即需要满足:问题的最优解中包含的子问题也是最优的。

        定义 F[i][j] :当前背包容量为 j ,考虑前 i 个物品的最佳组合对应的价值。

当考虑背包容量为 j ,前 i 个物品的选择时,有两种想法:

        ① 不选择第 i 件 物品 则 F[i][j]=F[i-1][j]

        ② 选择第 i 件 物品,则需要考虑到剩余的背包容量 j - w[ i ] :

                                ​​​​​​​        F[i][j]=F[i-1][j-w[i]]+v[i]

最终状态转移方程:

        j<w[i] \, \, \, \, \, \, \, \, F[i][j]=F[i-1][j]

        j>=w[i] \, \, \, \, \, \, \, \, \, \, \, \, F[i][j]=max(F[i-1][j],F[i-1][j-w[i]]+v[i])

        由于状态转移过程F[i][j]都是由原先的状态得到的,因此思想成立。

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int N=1010;
int f[N][N];
int v[N], w[N];
int n, m;
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>w[i]>>v[i];
	f[0][0]=0;
	for(int i=1;i<=n;i++)
		for(int j=0;j<=m;j++)
		{
			if(j<w[i])  f[i][j]=f[i-1][j];
			if(j>=w[i]) f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);
		}
	cout<<f[n][m]<<endl;
	return 0;
}

         3. 01背包问题的探索

        在上述状态转移方程的过程中可以发现,在每次状态更新后,之前存储的数据不会再次用到,从而造成了空间上的浪费,可以将上述情况的二维数组压缩成一维数组,这时的数组就是动态变化的了

        与二维数组不同的是,在第二次循环过程中,背包容量的循环量应当从大到小(m->w[i])避免同一件物品被反复选择。 例如:

        当一件物品的体积为 1  价值为 10,当背包容量的循环量从小到大时, 运行F[1]=10,循环继续进行,F[2]=max(F[2],F[2-1]+10)=20。 即选择该物品两次,与01背包问题仅有一件商品不符,该方法适用于完全背包问题(同一件商品可以取多次)

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int N=1010;
int f[N];
int v[N], w[N];
int n, m;
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>w[i]>>v[i];
	f[0][0]=0;
	for(int i=1;i<=n;i++)
	for(int j=m;j>=w[i];j--)  // 从后往前,避免同一件商品反复选择(01背包)
	{
		f[j]=max(f[j],f[j-w[i]]+v[i]);
	}
	cout<<f[m]<<endl;
	return 0;
}

二、完全背包问题

        题目描述

         有 N 件物品和一个容量是 V 的背包。每件物品数量为无限个。第 i 件物品的体积是 vi,价值是 wi。

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

        与01背包问题的唯一区别在于:完全背包的物品数量可以取无限个

        在01背包问题的讲述过程中已经明确解释了完全背包问题的解法:在01背包一维数组的情况下,将背包容量的循环量从小到大遍历,在数组不断更新的情况下能够让某件物品多次装入。

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int N=1010;
int f[N];
int v[N], w[N];
int n, m;
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>w[i]>>v[i];
	f[0][0]=0;
	for(int i=1;i<=n;i++)
	for(int j=w[i];j<=m;j++)  // 从前往后,能够让某件物品多次选择(完全背包问题)
	{
		f[j]=max(f[j],f[j-w[i]]+v[i]);
	}
	cout<<f[m]<<endl;
	return 0;
}

三、多重背包问题  

        1.题目描述

        有 N 件物品和一个容量是 V 的背包。第 i 件物品的体积是 vi,价值是 wi,数量是 ki。

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

        与前两种背包问题的联系:01背包和完全背包都是对于某种情况的极端,而多重背包问题则是介于二者之间,每个物品可以取不同个数的情况。

         根据多重背包与01背包,完全背包的关系,可以得出一个简单的想法:

        ①. 把多重背包问题变成01背包问题:

        即当某个物品有k个时,可以看作存在相同的体积,价值的k个不同的物品,这样就可以存在每个物品取一个或者取几个的情况。

        或者再利用一层循环 k 枚举该物品取的次数,保证存在取多次的情况。

        这种想法显然成立,但只适用于数量较少的情况,如果每种物品的数量变大,存在超时的情况,因此不是最优的解法

       ②.联系完全背包问题

        当背包不能装在某种物品的全部数量时,即(V<w[i]*k),则此时一定不能取完,可以看作完全背包问题,此时只需要简单的讨论即可。

        将多重背包转化成01背包和完全背包的结合只能进行小优化。

        2.多重背包问题的优化

        ① 二进制优化

                例如想要取512件物品时,按照转化成01背包问题,需要从第一件枚举512件,而采用二进制的想法,把每次取物品的件数分为1,2,4,8........256.512...2^n,枚举9次就取到512件了,此外每个数都可以用二进制数的组合来表示,例如 10=1+2+4+3   15=1+2+4+8

k=1;cnt=0;
while(k<=s)    //k为枚举个数,s为物品总件数
{
	v[++cnt]=k*a;
	w[cnt]=k*b;
	s-=k;       //总物品数减去合成数
	k*=2;       //k倍增
}
if(s)// s有剩余,将剩余件数合成为新个体
{
	v[++cnt]=s*a;
	w[cnt]=s*b;
}

 将每种物品的 k 都经过上述过程,构造出两个数组(存储有二进制数的数据)价值数组和重量数组,再通过01背包的思想,即可解决问题。

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

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

相关文章

不考408的985,不想考408的有福了!吉林大学计算机考研考情分析

吉林大学&#xff08;Jilin University&#xff09;简称吉大&#xff0c;位于吉林长春&#xff0c;始建于1946年&#xff0c;是中华人民共和国教育部直属的综合性全国重点大学&#xff0c;国家“双一流”、“211工程”、“985工程”、“2011计划”重点建设的著名学府&#xff0…

免费分享一套微信小程序商城系统(电商系统)(SpringBoot+Vue3)【至尊版】,帅呆了~~

大家好&#xff0c;我是java1234_小锋老师&#xff0c;自己原创写了一个不错的微信小程序商城系统(电商系统)(SpringBootVue3)【至尊版】&#xff0c;免费分享下哈。 项目视频演示 【免费】微信小程序商城系统(电商系统)(SpringBootVue3) 【至尊版】Java毕业设计_哔哩哔哩_bi…

【数据结构与算法】之五道链表进阶面试题详解!

目录 1、链表的回文结构 2、相交链表 3、随机链表的复制 4、环形链表 5、环形链表&#xff08;||&#xff09; 6、完结散花 个人主页&#xff1a;秋风起&#xff0c;再归来~ 数据结构与算法 个人格言&#xff1a;悟已往之不谏&#xff0c;知…

自动驾驶主流芯片及平台架构(二)特斯拉自动驾驶芯片平台介绍

早期 对外采购mobileye EyeQ3 芯片摄像头半集成方案&#xff0c;主要是为了满足快速量产需求&#xff0c;且受制于研发资金不足限制&#xff1b; 中期 采用高算力NVIDIA 芯片平台其他摄像头供应商的特斯拉内部集成方案&#xff0c;mobileye开发节奏无法紧跟特斯拉需求&#xff…

pyside6的调色板QPalette的简单应用

使用调色板需要先导入:from PySide6.QtGui import QPalette 调色板QPalette的源代码&#xff1a; class QPalette(Shiboken.Object):class ColorGroup(enum.Enum):Active : QPalette.ColorGroup ... # 0x0Normal : QPalette.ColorGrou…

基于C++基础知识的循环语句

一、while循环 while循环语句形式如下&#xff1a; while(表达式){语句 } 循环每次都是执行完语句后回到表达式处重新开始判断&#xff0c;重新计算表达式的值&#xff0c;一旦表达式的值为假就退出循环。用花括号括起来的多条简单语句&#xff0c;花括号及其包含的语句被称…

公网tcp转流

之前做过几次公网推流的尝试, 今天试了UDP推到公网, 再用TCP从公网拉下来, 发现不行, 就直接改用TCP转TCP了. 中间中转使用的python脚本, 感谢GPT提供技术支持: import socket import threadingdef tcp_receiver(port, forward_queue):"""接收TCP数据并将其放入…

【简单介绍下7-Zip】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

Fireworks AI和MongoDB:依托您的数据,借助优质模型,助力您开发高速AI应用

我们欣然宣布 MongoDB与 Fireworks AI 正携手合作 让客户能够利用生成式人工智能 (AI) 更快速、更高效、更安全地开展创新活动 Fireworks AI由 Meta旗下 PyTorch团队的行业资深人士于 2022 年底创立&#xff0c;他们在团队中主要负责优化性能、提升开发者体验以及大规模运…

五款优秀的局域网监控软件推荐:实时监控电脑屏幕的神器

在现代社会&#xff0c;计算机和网络已经成为工作中不可或缺的部分。随着局域网的普及&#xff0c;如何有效地监控和管理局域网内的电脑成为了许多企业和管理者关心的问题。本文将为您推荐五款优秀的局域网监控软件&#xff0c;帮助您实时监控电脑屏幕&#xff0c;提高工作效率…

宏电全栈式IoT赋能供排水智能监测,护航城市生命线

城市供水、排水系统是维系城市正常运行、满足群众生产生活需要的重要基础设施&#xff0c;是城市的“生命线”。随着城市化进程加快&#xff0c;城市规模不断扩大&#xff0c;地下管线增长迅速&#xff0c;城市“生命线安全”的监管日益面临挑战。 宏电作为物联网行业的领航者…

尊享面试100(272.最接近的二叉树搜索值|| python)

刚开始想着用最小堆&#xff0c;把每个元素都加进去&#xff0c;然后找出最小的k个值&#xff0c;复杂度应该是&#xff08;nklogn) import heapq as pq class Solution:def __init__(self):self.h []pq.heapify(self.h)def closestKValues(self, root: Optional[TreeNode], …

LLVM的ThinLTO编译优化技术在Postgresql中的应用

部分内容引用&#xff1a;https://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html LTO是什么&#xff1f; 链接时优化&#xff08;Link-time optimization&#xff0c;简称LTO&#xff09;是编译器在链接时对程序进行的一种优化。它适用于以文件为单位编译…

博客系统项目测试报告

文章目录 一.报告概要二.测试环境三.手工测试用例四.编写测试用例五.自动化测试Selenium测试项目主要特点 一.报告概要 项目概要 本项目是一个全功能的个人博客系统&#xff0c;旨在提供一个用户友好、功能全面的平台&#xff0c;允许用户注册、登录、浏览博客、查看详细内容、…

嵌入式学习

笔记 作业 有如下结构体 struct Student{ char name[16]; int age; double math_score; double chinese_score; double english_score; double physics_score; double chemistry…

Linux用户日志审计系统

标题日期版本说明作者 用户日志审计系统 2024.05.06v.0.0.1权限lgb 测试环境&#xff1a;CentOS Stream 9 测试过程&#xff1a; 测试开始前&#xff0c;首先我们先建立一个用户。 将文件备份。 我们通过vim编辑器&#xff0c;打开 /etc/profile 文件进行编辑。 将提前编辑好…

【C语言】第一个C程序:hello world

printf简介 printf是C语言提供的库函数&#xff0c;可以在屏幕上打印格式化数据。这里不作展开&#xff0c;只需要知道&#xff0c;如果要打印hello world&#xff0c;就把双引号引起来的"hello world"作为参数传给printf就行了。如果想要在打印后换行&#xff0c;要…

Scratch编程v3.29.1少儿编程工具

软件介绍 SCRATCH是一款由麻省理工学院&#xff08;MIT&#xff09;媒体实验室开发的图形化编程语言和集成开发环境&#xff08;IDE&#xff09;。它的目标是让编程变得有趣、直观且易学&#xff0c;尤其是针对儿童和青少年群体。通过SCRATCH&#xff0c;用户可以通过拖放代码…

python安装问题及解决办法(pip不是内部或外部命令也不是可运行)

pip是python的包管理工具&#xff0c;使python可在cmd&#xff08;命令行窗口&#xff0c;WinR后输入cmd&#xff09;中执行 针对 “pip不是内部或外部命令也不是可运行” 问题&#xff0c;需要在安装的时候将python添加到环境变量中 上图第三个选项必须勾选才能在cmd中使用pi…

今日详解,教你如何不直播在视频号卖货

大家好&#xff0c;我是电商笨笨熊 视频号作为背靠微信的平台&#xff0c;从不需要考虑自身的流量问题&#xff0c; 因此在视频号推出之后就有大批的主播从其他平台转入视频号&#xff1b; 而这时候很多普通人应该也发现了新的机会&#xff0c;不再去内卷抖音、快手直播&…