参考地址: [0-1背包问题的动态规划算法](https://zhuanlan.zhihu.com/p/30959069) [01背包问题 图解+详细解析 (转载)](https://blog.csdn.net/qq_37767455/article/details/99086678) [背包九讲——全篇详细理解与代码实现](https://blog.csdn.net/yandaoqiusheng/article/details/84782655/) ### 1、通过递归的方式实现 递归的理解: 理解这边的参数 bagItemList代表所有的物品(包含重量和价值) 、 index表示当前要装入背包的物品的位置 -- 第一二个参数组成了当前要装入背包的物品信息 第三个参数表示 当前剩余的背包容量,也就是说对于当前index位置的物品来说,此时还有多少容量剩余. 结束条件是 所有物品都尝试装入完毕 或者 当前容量小于0,没办法再装入其他道具. 算法的整个过程表现为:尝试装入第index位置的道具,当前容量是减去之前装入道具重量后剩余的容量 假设我们这么理解,从最后一个道具去装(本质上没有顺序),这个时候背包容量是原始容量.如果道具重量非常大,不满足背包容量,则这个道具压根没办法装入,不管他. 这边有两种情况,一个是装入index位置的道具,一个是不装入index位置的道具. 不装index位置的道具,则这个时候容量是背包最大的容量,如果装入index位置的道具,则背包容量变小,留给index-1位置的容量就是 (背包容量 - index位置重量) 对于不装index位置的道具,最大价值是前index-1个道具的最优解,而装入index位置的道具,拿到的就是前index个道具的最优解 以此类推。我们取这两个值的max,就可以保证递归回来的时候拿到的永远是最优解. ![](/.readme_images/递归解背包问题.jpg) ### 2、通过动态规划的方式实现 通过动态规划的方式来解答背包问题,这边需要在背包道具初始化的时候去创建一个辅助数组 也就是说数组的展示方式是按照下面的方式进行处理的。 也就是说这边的横坐标是背包的容量。 纵坐标是当前拥有的道具的数量,道具按照顺序去增加,也就是说当道具数量为1的时候, 这个时候拥有第一个道具,道具数量为2的时候,这个时候拥有第二个道具, 这么处理是为了实现当容量在一定数量的情况下,拥有n个道具能达到的最优解是多少。 也就是我们在递归里面看到的,index位置的道具比较的是 max(前index-1个道具的最优解,index位置的道具 + 减去index位置重量的前index-1个道具的最优解) ![](/.readme_images/动态规划解背包问题.png) ### 3、动态规划(一维数组简化空间复杂度) 一维数组实现背包求解同样需要辅助列,也就是当背包容量为0,作为辅助列,数组的长度是背包容量+1,分表表示容量为0、1、2、3...最大容量 从第一个道具开始到最后一个道具计算,每次分成两种情况,一个是装入该道具,一个是不装入该道具. 装入该道具的时候:计算的总价值是 当前道具价值 + List[当前容量 - 道具重量] 不装入该道具的时候:计算的总价值就是原来数组的价值,即 List[当前容量] 从第一个道具开始,一旦小于该道具价值,表示道具没办法装入该容量的背包的时候,停止计算。第二个道具在计算的时候同样是分成两种情况, 计算得到的值就是第一个道具放入与不放入两种情况中的最优解,同理一直到最后一个道具为止 计算结束,返回的List[背包总容量]表示的就是在背包总容量的情况下的最优解 这种方式虽然简化了存储空间,但是也因为覆盖对应的数据,导致如果要查找对应的道具最优解路径没办法完整还原。 ![](/.readme_images/动态规划解背包问题(优化数组).jpg)