【动态规划】背包问题

article/2025/10/3 1:49:47

注意:for j in range(1,m+1):是枚举所有的情况,不用一一判断放入物品后背包容量减少后j的变化。为什么从1开始,因为0已经写出来了,即dp[i-1][j]=dp[i-1][j-0*a[i-1]]+0*v[i-1]

01背包无价值

dp定义:前i项物品中的所有排序对应的当前重量(由给定数组决定)就为j的值,将此dp[i][j]=True表示就给的数组的前i项可以组成重量为j的组合。自然dp[i][0]都是True,不用放入物品自然是0。

for循环从m开始是因为题目要求最多装多少,故先从最大的开始。

        dp=[[False]*(m+1) for i in range(n+1)]dp[0][0]=Truefor i in range(1,n+1):dp[i][0]=Truefor j in range(1,m+1):if j-a[i-1]>=0:dp[i][j]=dp[i-1][j] or dp[i-1][j-a[i-1]]else:dp[i][j]=dp[i-1][j]for i in range(m,-1,-1):if dp[n][i]==True:return ibreak

01背包有价值

        dp=[[0]*(m+1) for i in range(n+1)]#dp[0][j]=0,初始化前0项的价值为0for i in range(1,n+1):for j in range(1,m+1):if j-a[i-1]>=0:dp[i][j]=max(dp[i-1][j],dp[i-1][j-a[i-1]]+v[i-1])else:dp[i][j]=dp[i-1][j]return dp[n][m]

完全背包问题

max(dp[i-1][j],dp[i-1][j-a[i-1]]+v[i-1])实际上可以写成max(dp[i-1][j-0*a[i-1]]+0*v[i-1],dp[i-1][j-1*a[i-1]]+1*v[i-1])

依次类推多重背包就可以写成:

for count in range(j//a[i-1]+1):

        max(dp[i-1][j-0*a[i-1]]+0*v[i-1],dp[i-1][j-1*a[i-1]]+1*v[i-1],dp[i-1][j-2*a[i-1]]+2*v[i-1]......)

        n=len(a)dp=[[0]*(m+1) for i in range(n+1)]for i in range(1,n+1):for j in range(m+1):for count in range(j//a[i-1]+1):dp[i][j]=max(dp[i][j],dp[i-1][j-count*a[i-1]]+count*v[i-1])return dp[n][m]

但是会超时

优化

        放第i件物品时。这里的处理和01背包有所不同,因为01背包的每个物品只能选择一个,因此选择放第i件物品就意味着必须转移到dp[i-1][v-w[i]]这个状态;

        但是完全背包不同,完全背包如果选择放第i件物品之后并不是转移到dp[i-1][v-w[i]],而是转移到dp[i][v],这是因为每种物品可以放任意件(注意有容量的限制,因此还是有限的),放了第i件物品后还可以继续放第i件物品,直到第二维的v-w[i]无法保持大于等于0为止。

        注意(for j in range(a[i-1],m+1):整个过程表示当前i-1个商品选完时该选则第i个商品,a[i-1]一直放,每一次放的次数不同所对应的j不同,直到到装不下时(即j<a[i-1]) ,而且每一次都是根据第i-1个商品所得到的关于j的一维列表得到的,也是一个i个商品对应的关于j一维列表。

        关于状态方程为什么是dp[i][j]=max(dp[i-1][j],dp[i][j-a[i-1]]+v[i-1]),因为dp[i][j]是先从dp[i-1][j]转移过来,然后再进行a[i][j]的数量选择,即dp[i][j-a[i-1]]。

n=len(a)
dp=[[0]*(m+1) for i in range(n+1)]
for i in range(1,n+1):for j in range(a[i-1],m+1):dp[i][j]=max(dp[i-1][j],dp[i][j-a[i-1]]+v[i-1])return dp[n][m]

多重背包

我们考虑一下,如果所有ni都满足ni ≥ W / wi,那不就变成完全背包的问题了么。可见,完全背包的基本实现思路也可以应用到多重背包的基本实现。对于多重背包的基本实现,与完全背包是基本一样的,不同就在于物品的个数上界不再是v/c[i]而是n[i]与v/c[i]中较小的那个。所以我们要在完全背包的基本实现之上,再考虑这个上界问题。

这次我们直接空间优化,不再讲解二维做法:

多重背包是可以不选,也可以选 1 个,可以选多个,而 0-1 背包只能选 0 个或者 1 个。

那就直接把种物品分开,即可比如:

每个盘子 3 块钱,我有 2 个。每双筷子 1 块钱,我有 10 双,每对刀叉 3 块钱,我有 3 个。

那么我就可以拆成,有 2 个三块的盘子,每个可以选也可以不选,就变成了 0-1 背包。

也就是说,对于每种是可以选多个,那就直接拆分成独立的个体就可以了。

代码与完全背包的区别除了多了个表示物品个数的数组s[ ]之外,只在内循环的控制条件那里。

        n=len(a)dp=[[0]*(m+1) for i in range(n+1)]for i in range(1,n+1):for j in range(1,m+1):for k in range(min(j//a[i-1]+1,s[i])+1)):dp[i][j]=max(dp[i][j],dp[i-1][j-k*a[i-1]]+k*v[i-1])return dp[n][m]

滚动数组(空间优化(二维变一维)

01背包

因为状态转移每次只与上一层有关,所以用一个一维数组就可以。

为什么从大到小遍历?

看 dp[j]=dp[j-c[i]]+w[i]这一状态转移,

为什么从c[i]开始,是因为j不能小于c[i]

为什么是逆序呢,因为在第一次i=0的for循环时,所有满足range(c[i],C+1)的dp[j]都是w[I],所有的dp[j - c[i]]都是0,因为第一次之前的价值均为0,

可能有人要问了,第一次的j难道不都是C吗,是都是,但是其他不是C的但是大于c[i]的可以不用管。

如果从小到大则当循环到大的j时,dp[j - c[i]]不一定等于0。

是根据小的改大的,如果先把小的改了,那小的还会被用到,数据就不对了,所以从小到大。

        为什么是逆序遍历?,这个是根据原状态方程判断的由dp[i][j]=max(dp[i-1][j],dp[i-1][j-a[i-1]]+v[i-1])可知,dp[i][j]是由上方i-1层和左边一直到j为止的一维数据转换而来,变到一维dp[j] = max(dp[j - a[i]] + v[i], dp[j])则是由之前i-1次的一维列表的转换而来,因为是靠旧的且是左侧的数据,所以就要从大到小开始遍历(如果是靠右边的旧数据,则是从小到大)

        注意到状态转移方程中计算dp[i][v]时总是只需要dp[i-1][v]左侧部分的数据(即只需要图中正上方与左上方的数据),且当计算dp[i+1][ ]的部分时, dp[i-1]的数据又完全用不到了(只需要用到dp[i][ ]),因此不妨可以直接开一个一维数组dp[v](即把第一维省去),枚举方向改变为i从1到n,v从V到0(逆序!),

    for i in range(n):for j in reversed(range(a[i],m+1)):dp[j] = max(dp[j - a[i]] + v[i], dp[j])print(dp[m])

完全背包

空间优化:

未省略取物品次数k的等价转换代码:

for i in range(1, N + 1):for j in reversed(range(a[i],m+1)):for k in range(0, j // a[i] + 1):dp[j] = max(dp[j], dp[j - k * a[i]] + k * v[i])print(dp[m])

因为状态转移每次只与上一层有关,所以用一个一维数组就可以。

为什么这次是从小到大遍历了呢?

是根据小的改大的,而此时的含义为选了 x 件后的容量与质量,跟第一个类似,但含义不同,所以子处理方式上也有本质区别,处理完一件后在处理下件。

完全背包的一维数组实现和01背包也是几乎完全相同,唯一差别是完全背包的内循环是正向遍历,而01背包的内循环是逆向遍历。

省略取物品次数k的等价转换代码:

        为什么是又变成了正序,这次还看原状态方程dp[i][j]=max(dp[i-1][j],dp[i][j-a[i-1]]+v[i-1]),可知dp[i][j]是由右上一层即i-j层正上方(在一维中直接是dp[j] =dp[j])和右测以j开头的数据得到因为dp[i][j]=dp[i][j-a[i-1]]中左侧的j小于右测的j。故一维状态方程为正序。

        怎么理解必须正向枚举呢?求解dp[i][v]需要它左边的dp[i][v-w[i]]和它上方的dp[i-1][v],显然如果让v从小到大枚举,dp[i][v-w[i]]就总是已经计算出的结果;而计算出dp[i][v]之后dp[i-1][v]就再也用不到了,可以直接覆盖。

        为什么可以覆盖,因为物品可以多次取出,每多取一次都是在覆盖。

    for i in range(n):for j in range(a[i],m+1):dp[j] = max(dp[j - a[i]] + v[i], dp[j]);print(dp[m])

多重背包

还是看原状态方程dp[i][j]=max(dp[i][j],dp[i-1][j-k*a[i-1]]+k*v[i-1])

    for i in range(n):for j in reversed(range(a[i],m+1)):for k in range(s[i]+1):if j<k*a[i]:breakdp[j] = max(dp[j], dp[j - k * a[i]] + v[i] * k)print(dp[m])


http://chatgpt.dhexx.cn/article/mbwLS3qi.shtml

相关文章

动态规划——背包问题(01背包问题)

动态规划——背包问题&#xff08;01背包问题&#xff09;01背包问题(求最大价值)&#xff1a;问题优化01背包问题(求方案数)&#xff1a; 动态规划——背包问题&#xff08;01背包问题&#xff09; 01背包问题(求最大价值)&#xff1a; 有N件物品和一个最多能背重量为W的背包…

动态规划:关于01背包问题 I

动态规划&#xff1a;关于01背包问题&#xff0c;你该了解这些&#xff01; 对于面试的话&#xff0c;其实掌握01背包&#xff0c;和完全背包&#xff0c;就够用了&#xff0c;最多可以再来一个多重背包。 如果这几种背包&#xff0c;分不清&#xff0c;我这里画了一个图&…

c++ 动态规划-01背包

动态规划 - 01背包问题 1.使用递归遍历(穷举)求解&#xff1a; 01背包问题&#xff1a;给定 n 种物品和一个重量(容量)(限定条件)为 w 的背包,物品 i 的重量是 wi,其价值为 vi。(每种物品只有一个)问:如何选择装入背包的物品,使得装入背包中的物品的价值最大。 //VC6.0------…

动态规划——01背包问题(C++实现)

题目描述&#xff1a; 解题思路&#xff1a; 整体思路&#xff1a; 利用动态规划&#xff0c;其目的就是将原问题分解成几个子问题&#xff0c;通过求解简单的子问题&#xff0c;把原问题给解决&#xff0c;就比如斐波那契数列方程&#xff1a; f[i]f[i-1]f[i-2]; 动态规划的…

动态规划总结三01背包问题

01背包问题一般是利用动态规划进行解题的&#xff0c;这里通过leetcode1049来讲解01背包的解题思路以及如何对01背包应用题目转换和理清思路 01背包问题&#xff1a; 这里借用学习公众号代码随想录的一张图来说明背包问题的种类 对于面试的话&#xff0c;其实掌握01背包&…

dp 动态规划 01背包问题 Python

参考学习网址&#xff1a; https://www.bilibili.com/video/av33930433?fromsearch&seid10637513335818789097 https://www.cnblogs.com/anzhengyu/p/11408466.html 问题描述&#xff1a; 给定 n 件物品&#xff0c;物品的重量为 w[i]&#xff0c;物品的价值为 v[i]。现…

Python3使用动态规划处理01背包问题

文章目录 视频教程讲解题目介绍题解1&#xff1a;二维列表题解2&#xff1a;一维列表&#xff08;滚动数组&#xff09;延伸阅读 视频教程讲解 【Python算法系列】动态规划2-01背包问题&完全背包问题【Python算法实战】背包问题 题目介绍 原题链接&#xff1a;NC145 01背…

算法 动态规划 01背包问题

01背包 问题分析代码实现从前往后拿&#xff0c;递归实现非递归实现非递归实现&#xff0c;自上向下填充 允接上一文章内容&#xff1a; 算法 动态规划: link. 问题分析 按照普通思维&#xff0c;首先想到应该为贪心算法&#xff0c;也就是计算每个物品重量价值比&#xff0c;…

【动态规划】01背包问题

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位喜欢写作&#xff0c;计科专业大二菜鸟 &#x1f3e1;个人主页&#xff1a;starry陆离 &#x1f552;首发日期&#xff1a;2022年5月16日星期一 &#x1f30c;上期文章&#xff1a;【动态规划】最长上升子序列 &#x1f4…

01背包问题:图表法带你快速理解动态规划解决01背包问题 附C++源码

0-1背包问题 所谓0-1背包问题&#xff0c;也就是给你一个重量为M的背包和n种物品&#xff0c;每种物品有一定的重量和价值&#xff0c;在每种物品均可装入背包1次或不装入&#xff08;不能仅装入物品的一部分&#xff09;且不超过背包载重量的前提下&#xff0c;问你怎样选择物…

动态规划——0/1背包问题(全网最细+图文解析)

✨动态规划——0/1背包问题(全网最细图文解析) 作者介绍: &#x1f393;作者:青花瓷✨ &#x1f440;作者的Gitee:代码仓库 &#x1f4cc;系列文章推荐: ✨1.数据结构与算法—算法篇之动态规划(一) ✨2.【Java刷题特辑第一章】——【点进来花两把游戏的时间学习晚上睡觉都踏实了…

【动态规划】01背包问题(通俗易懂,超基础讲解)

问题描述 有n个物品&#xff0c;它们有各自的体积和价值&#xff0c;现有给定容量的背包&#xff0c;如何让背包里装入的物品具有最大的价值总和&#xff1f; 为方便讲解和理解&#xff0c;下面讲述的例子均先用具体的数字代入&#xff0c;即&#xff1a;eg&#xff1a;numbe…

java事务和分布式事务详解

目录 事务问题 1 Java事务的类型 2 spring事务实现源码分析 事务问题 面试经常会问到分布式锁、分布式事务、SOA 服务化、分布式系统等业务、架构的问题和解决方案&#xff0c;工作中接触的业务方面事关金融&#xff0c;也需要解决一些类似的业务问题&#xff0c;所以总结…

JAVA事务配置总结

JAVA事务配置总结 使用hibernate&#xff1a;1.本地事务动态数据源单sessionFactory 这种情况属于大部分项目配置&#xff0c;在这里不多谈 2.全局事务动态数据源单sessionFactory 数据库分库分表时使用&#xff0c;已解决了不同库中相同名字的表相同ID的数据同时出现在同一…

Java事务回滚问题:抛出异常事务,并返回给前端异常信息

1、背景 修改bug。 之前的开发写的只能单选&#xff0c;所以逻辑都是按照只需要传递一个id值的逻辑写的 现在改为多选时&#xff0c;传递过来的是id数组&#xff0c;所以直接原逻辑的外层加了一个循环&#xff0c;这样原逻辑包括sql就不需要大变动&#xff0c; 但是这样会有个…

java事务中使用try catch 导致事务不回滚的问题

Transactional注解的触发&#xff0c;只回滚RuntimeException和Error异常&#xff0c;默认不回滚非RuntimeException异常 解决方法&#xff1a; 1.方法前添加注解&#xff08;基础的 Transactional注解&#xff1a;只能拦截RuntimeException和Error异常&#xff09; Transa…

java中事务

1.开启事务 事务的四大特性 ACID是原子性&#xff08;atomicity&#xff09;、一致性&#xff08;consistency&#xff09;、隔离性 &#xff08;isolation&#xff09;和持久性&#xff08;durability&#xff09;的缩写。 事务的原子性&#xff1a;事务作为整体执行&#x…

Java事务的ACID属性和四种隔离级别和传播机制

事务的ACID属性 数据库管理系统中事务(transaction)的四个特性&#xff08;分析时根据首字母缩写依次解释&#xff09;&#xff1a;原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔离性&#xff08;Isolation&#xff09;、持久性&a…

java回滚失败_java事务回滚失败问题分析

Spring-Java事物回滚失效处理最近在做项目中,无意间发现有个类在抛事物回滚操作,数据也正常的插入到数据库当中了,于是仔细查看看一下具体原因。 一切还是要从Java的检查型异常和非检查型异常说起。 那么什么是检查型异常什么又是非检查型异常呢? 最简单的判断点有两个: 1…

java中事务特性_java事务的四大特性ACID

前言 对于要把事务在实际中使用好&#xff0c;需要了解事务的特性。 事务的四大特性主要是&#xff1a;原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。 一、事务的四大特性 1.1原子性(Atomicity) 原子性是指事务是一个不可分割的工作单位&a…