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

一、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.mzph.cn/pingmian/7111.shtml

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

相关文章

客户管理软件排行榜:对比18款CRM

本文将对比18个客户管理软件&#xff1a;纷享销客、Zoho CRM、Salesforce、HubSpot CRM、Pipedrive、Freshsales、Microsoft Dynamics 365 CRM、Insightly CRM、Nimble CRM、Apptivo CRM、SugarCRM、白码CRM、简信CRM、销帮帮CRM、Teamface企典CRM、神州云动CRM、悟空CRM、八百…

由于找不到msvcp120.dll,无法继续执行代码的5种解决方法

在操作计算机的过程中&#xff0c;您或许会遇到这样一种情形&#xff1a;当试图启动某个软件应用程序时&#xff0c;系统突然弹出一个错误提示框&#xff0c;明确指出“找不到msvcp120.dll”&#xff0c;它会导致程序无法正常启动或运行。为了解决这个问题&#xff0c;我总结了…

详细分析Java中的@Service注解

目录 1. 基本知识2. Demo2.1 传统形式2.2 注解形式 3. 总结 1. 基本知识 Service 是 Spring Framework 中的一个注解&#xff0c;用于标识一个类为服务层组件 服务层&#xff08;Service Layer&#xff09;&#xff1a; 服务层是应用程序的一个层次结构&#xff0c;位于控制层…

OpenNJet:云原生技术中的创新者与实践者

目录 引言OpenNJet介绍OpenNJet优势1. 性能无损动态配置2. 灵活的CoPilot框架3. 支持HTTP/34. 支持国密5. 企业级应用6. 高效安全 OpenNJet 编译与安装环境准备编译环境配置配置yum源yum 安装软件包创建符号连接修改 ld.so.conf 配置 编译代码 部署 WEB SERVER配置OpenNJet部署…

深入探索JDK:Java开发工具包的奥秘

深入探索JDK&#xff1a;Java开发工具包的奥秘 随着信息技术的飞速发展&#xff0c;Java作为一种广泛使用的编程语言&#xff0c;在各个领域都发挥着重要作用。而JDK&#xff08;Java Development Kit&#xff0c;Java开发工具包&#xff09;作为Java编程的基础&#xff0c;其…

k8s的架构组成

一 k8s的概述 1.1 概述 k8s是一个轻便的和可扩展的开源平台&#xff0c;用于管理容器化应用和服务&#xff0c;通过k8s能够进行应用的自动化部署和扩缩容。 k8s可以创建多个容器&#xff0c;每个容器运行一个应用实例&#xff0c;然后通过内置的负载均衡策略&#xff0c;实现…

Docker安装gitlab后连接内置pgsql修改用户信息

Docker安装gitlab后连接内置pgsql修改用户信息 进入gitlab容器 docker exec -it gitlab /bin/bash 进入postgresql su - gitlab-psql 连接pgsql psql -h /var/opt/gitlab/postgresql -d gitlabhq_production 命令行直接执行SQL语句 psql -h /var/opt/gitlab/postgresql…

HCIP-Datacom-ARST必选题库_BGP【道题】

1.关于summary automatic命令和BGP聚合的描述,错误的是? 该命令用于实现自动聚合,其优先级高于手动聚合 配置该命令后,BGP将按自然网段聚合路由 该命令用来使能对本地引入的路由进行自动聚合 配置该命令后,BGP只向对等体发送聚合后的路由 1.关于summary automatic命令和BGP聚…

Vue入门到关门之Vue3项目创建

一、vue3介绍 1、为什么要学习vue3&#xff1f; vue3的变化&#xff1a; 首先vue3完全兼容vue2&#xff0c;但是vue3不建议用vue2的写法&#xff1b;其次&#xff0c;vue3拥抱TypeScript&#xff0c;之前vue2使用的JavaScript&#xff0c;ts完全兼容js 最后之前学的vue2 是…

面试经典150题——找出字符串中第一个匹配项的下标

面试经典150题 day23 题目来源我的题解方法一 库函数方法二 自定义indexOf函数方法三 KMP算法 题目来源 力扣每日一题&#xff1b;题序&#xff1a;28 我的题解 方法一 库函数 直接使用indexOf函数。 时间复杂度&#xff1a;O(n) 空间复杂度&#xff1a;O(1) public int str…

(数据分析方法)长期趋势分析

目录 一、定义 二、目的 三、方法 1、移动平均法 (1)、简单移动平均法 (2)、加权移动平均法 (3)、指数平滑法 2、最小二乘法 3、线性回归 1、数据预处理 2、观察数据分布建立假设模型 3、定义损失函数 4、批量梯度下降 5、优化 4、LSTM 时序分析 5、特征工程 一…

vue3中的reactive和ref

&#x1f30f;总结&#xff1a;reactive 适用于创建复杂的响应式对象&#xff0c;而 ref 则适用于创建简单的响应式值。 reactive 和 ref 是 Vue 3 Composition API 中用于创建响应式数据的两种主要方式&#xff0c;它们的作用如下&#xff1a; 响应式数据管理&#xff1a; rea…

OCC笔记:图形可视化的实现方式

注&#xff1a;文中参看的occ的源码版本为7.4.0 1、实现思路概览 整体架构 主要有3大块&#xff1a;AIS&#xff08;Application Interactive Services &#xff0c;直译为&#xff1a;应用程序交互服务&#xff09;、Graphics&#xff08;图形&#xff09;、Geometry & T…

嵌入式交叉编译:Unable to find arm_neon.h

找到文件 搜索了一下&#xff0c;具体目录是&#xff1a; /opt/linux/x86-arm/aarch64-mix210-linux/lib/gcc/aarch64-linux-gnu/7.3.0/include/arm_neon.h 解决办法 INC_ARM/opt/linux/x86-arm/aarch64-mix210-linux/lib/gcc/aarch64-linux-gnu/7.3.0/include./configure …

Spring Security + JWT 实现登录认证和权限控制

Spring Security JWT 实现登录认证和权限控制 准备步骤 准备好一些常用的工具类&#xff0c;比如jwtUtil&#xff0c;redisUtil等。引入数据库&#xff0c;mybatis等&#xff0c;配置好controller&#xff0c;service&#xff0c;mapper&#xff0c;保证能够正常的数据请求。…

书籍推荐|经典书籍ic书籍REUSE METHODOLOGY MANUALFOR等和verilog网站推荐(附下载)

大家好&#xff0c;今天是51过后的第一个工作日&#xff0c;想必大家都还没有完全从节假日的吃喝玩乐模式转变为勤勤恳恳的打工人模式&#xff0c;当然也包括我&#xff0c;因此这次更新主要是分享几篇书籍和verilog相关的学习网站~ 首先是一本数字电路相关的基础书籍&#xf…

如何让你的排单更快?

一般我们都喜欢做打板借用快速通道&#xff01;但是目前快速通道也是共享通道&#xff0c;独立单元格基本不开发。 想要排单更快&#xff0c;想要隔夜打板&#xff0c;我们到底应该怎么做呢&#xff1f; 想要排单更快&#xff0c;说白了就是要提高你的交易速度&#xff01;一&a…

ld.exe: unrecognized option ‘--major-image-version‘

问题&#xff1a;在windows环境使用cmakemingw32gcc交叉工具链报错 原因&#xff1a;将project指令放到了set(CMAKE_SYSTEM_NAME Linux)之前 下面为CMakeLists.txt正确写法&#xff1a; cmake_minimum_required(VERSION 3.0)#set(CMAKE_C_COMPILER_WORKS 1)#set(CMAKE_CXX_C…

性能超越!新模型Dragoman打造高质量英译乌翻译系统,打败现有SOTA模型

DeepVisionary 每日深度学习前沿科技推送&顶会论文分享&#xff0c;与你一起了解前沿深度学习信息&#xff01; 引言&#xff1a;探索乌克兰语的机器翻译挑战 在当今全球化迅速发展的背景下&#xff0c;机器翻译技术已成为沟通世界各地文化和语言的重要桥梁。尽管如此&…

PMO全面指南:一文读懂PMO的功能、职责、类型、构建

多年来&#xff0c;PMO 的概念在多个行业和类型的组织中越来越受欢迎。一开始&#xff0c;只有大型跨国公司才熟悉它&#xff0c;但后来&#xff0c;许多中小型公司开始采用 PMO 来进行高效的项目管理并实现其战略目标。 根据Statista的数据&#xff0c;目前有80%的组织设有至…