背包问题01 左手的ㄟ右手 2022-01-29 11:34 353阅读 0赞 ## 题目 ## 有N件物品和一个容量为V的背包。第i件物品的费用是c\[i\],价值是w\[i\]。求解将哪些物品装入背包可使价值总和最大。 **基本思路** 这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。 用子问题定义状态:即f\[i\]\[v\]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是: **f\[i\]\[v\]=max\{f\[i-1\]\[v\],f\[i-1\]\[v-c\[i\]\]+w\[i\]\}** 这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的。所以有必要将它详细解释一下:“**将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为f\[i-1\]\[v\];如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-c\[i\]的背包中”,此时能获得的最大价值就是f\[i-1\]\[v-c\[i\]\]再加上通过放入第i件物品获得的价值w\[i\]**。 **优化空间复杂度** 以上方法的时间和空间复杂度均为O(N\*V),其中时间复杂度基本已经不能再优化了,但空间复杂度却可以优化到O(V)。 先考虑上面讲的基本思路如何实现,肯定是有一个主循环i=1…N,每次算出来二维数组f\[i\]\[0…V\]的所有值。那么,如果只用一个数组f\[0…V\],能不能保证第i次循环结束后f\[v\]中表示的就是我们定义的状态f\[i\]\[v\]呢?f\[i\]\[v\]是由f\[i-1\]\[v\]和f\[i-1\]\[v-c\[i\]\]两个子问题递推而来,能否保证在推f\[i\]\[v\]时(也即在第i次主循环中推f\[v\]时)能够得到f\[i-1\]\[v\]和f\[i-1\]\[v-c\[i\]\]的值呢?事实上,这要求在每次主循环中我们以v=V…0的顺序推f\[v\],这样才能保证推f\[v\]时f\[v-c\[i\]\]保存的是状态f\[i-1\]\[v-c\[i\]\]的值。伪代码如下: for i=1..N forv=V..0 f[v]=max{f[v],f[v-c[i]]+w[i]}; 其中的f\[v\]=max\{f\[v\],f\[v-c\[i\]\]\}一句恰就相当于我们的转移方程f\[i\]\[v\]=max\{f\[i-1\]\[v\],f\[i-1\]\[v-c\[i\]\]\},因为现在的f\[v-c\[i\]\]就相当于原来的f\[i-1\]\[v-c\[i\]\]。如果将v的循环顺序从上面的逆序改成顺序的话,那么则成了f\[i\]\[v\]由f\[i\]\[v-c\[i\]\]推知,与本题意不符,但它却是另一个重要的背包问题P02最简捷的解决方案,故学习只用一维数组解01背包问题是十分必要的。 事实上,使用一维数组解01背包的程序在后面会被多次用到,所以这里抽象出一个处理一件01背包中的物品过程,以后的代码中直接调用不加说明。 过程ZeroOnePack,表示处理一件01背包中的物品,两个参数cost、weight分别表明这件物品的费用和价值。 procedure ZeroOnePack(cost,weight) forv=V..cost f[v]=max{f[v],f[v-cost]+weight} 注意这个过程里的处理与前面给出的伪代码有所不同。前面的示例程序写成v=V…0是为了在程序中体现每个状态都按照方程求解了,避免不必要的思维复杂度。而这里既然已经抽象成看作黑箱的过程了,就可以加入优化。费用为cost的物品不会影响状态f\[0…cost-1\],这是显然的。 有了这个过程以后,01背包问题的伪代码就可以这样写: for i=1..N ZeroOnePack(c[i],w[i]); #### 初始化的细节问题 #### 我们看到的求最优解的背包问题题目中,事实上有两种不太相同的问法。有的题目要求“恰好装满背包”时的最优解,有的题目则并没有要求必须把背包装满。一种区别这两种问法的实现方法是在初始化的时候有所不同。 如果是第一种问法,要求恰好装满背包,那么在初始化时除了f\[0\]为0其它f\[1…V\]均设为-∞,这样就可以保证最终得到的f\[N\]是一种恰好装满背包的最优解。 如果并没有要求必须把背包装满,而是只希望价格尽量大,初始化时应该将f\[0…V\]全部设为0。 为什么呢?可以这样理解:初始化的f数组事实上就是在没有任何物品可以放入背包时的合法状态。如果要求背包恰好装满,那么此时只有容量为0的背包可能被价值为0的nothing“恰好装满”,其它容量的背包均没有合法的解,属于未定义的状态,它们的值就都应该是-∞了。如果背包并非必须被装满,那么任何容量的背包都有一个合法解“什么都不装”,这个解的价值为0,所以初始时状态的值也就全部为0了。 这个小技巧完全可以推广到其它类型的背包问题,后面也就不再对进行状态转移之前的初始化进行讲解。 小结 01背包问题是最基本的背包问题,它包含了背包问题中设计状态、方程的最基本思想,另外,别的类型的背包问题往往也可以转换成01背包问题求解。故一定要仔细体会上面基本思路的得出方法,状态转移方程的意义,以及最后怎样优化的空间复杂度。
相关 01背包问题 [0-1背包问题][0-1] Reference: https://www.jianshu.com/p/a66d5ce49df5 问题描述: 0-1背包问题:给定 ﹏ヽ暗。殇╰゛Y/ 2022年10月11日 13:40/ 0 赞/ 280 阅读
相关 01背包问题 1.题目 有N件物品和一个容量为V的背包。第i件物品的成本是c\[i\],价值是w\[i\]。求解将哪些物品装入背包可使价值总和最大,要求是:物品只能放一次。 2.分 系统管理员/ 2022年09月10日 11:27/ 0 赞/ 233 阅读
相关 背包问题-背包01-苹果 package 动态规划.背包01; import java.util.Scanner; public class 苹果 \{ static class 野性酷女/ 2022年07月12日 12:12/ 0 赞/ 282 阅读
相关 01背包问题 ![Center][] ![Center 1][] [Center]: /images/20220616/e1a67e5ed0214bac8ec5293bc2b54 ╰+攻爆jí腚メ/ 2022年06月16日 14:46/ 0 赞/ 264 阅读
相关 01背包问题 public class package0_1 { int V[][] = new int[200][200];//物品选取,背包承重 int max( 约定不等于承诺〃/ 2022年06月08日 06:15/ 0 赞/ 262 阅读
相关 01背包问题 【例9.11】01背包问题 时间限制: 1000 ms 内存限制: 65536 KB 【题目描述】 一个旅行者有一个最多能装M公斤的背包,现在有n件物 淩亂°似流年/ 2022年06月08日 03:59/ 0 赞/ 257 阅读
相关 背包问题—01背包、完全背包 01背包问题 题目 有m件物品和一个容量为V 的背包。放入第i 件物品占用的体积是Vi,得到的价值是Wi。求解将哪些物品装入背包可使价值总和最大。 思路 这 末蓝、/ 2022年05月30日 10:10/ 0 赞/ 397 阅读
相关 01背包问题 简单背包问题 设有一个背包可以放入的物品重量为S,现有n件物品,重量分别是w1,w2,w3,…wn。 问能否从这n件物品中选择若干件放入背包中,使得放入的重量之和正好为S 痛定思痛。/ 2022年05月26日 12:18/ 0 赞/ 257 阅读
相关 01背包问题 转载:[https://blog.csdn.net/xp731574722/article/details/70766804][https_blog.csdn.net_xp73 怼烎@/ 2022年05月06日 15:00/ 0 赞/ 326 阅读
相关 背包问题01 题目 有N件物品和一个容量为V的背包。第i件物品的费用是c\[i\],价值是w\[i\]。求解将哪些物品装入背包可使价值总和最大。 基本思路 这是最基础的背包问题,特 左手的ㄟ右手/ 2022年01月29日 11:34/ 0 赞/ 354 阅读
还没有评论,来说两句吧...