数据结构与算法
背包问题02
题目类型描述: 给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高(from 百度百科)。
具象理解:
假设背包总容量top_weight为10,现共有四样物品(每样各一个),他们的重量和价格分别为:
抽象建模:
我们可以构建一个二维数组(或两个数组),在第一行存储各个物品的价格,第二行存储其重量,接下来电脑要做的事情就是根据我们给出的top_weight,从这n个物品中给出方案。
前言:
依然是和上一期一样的问题,其中最后提出的方法优化后时间复杂度为O(c*n)。我们先回顾一下自下而上填表法:
首先构建这样一个5行11列的表格:
其中添加了i=0和j=0的情况(i,j各自表示可取前i个物品,背包剩余可容纳重量为j)是方便我们填表,减少空指针报错的可能。i=2,j=3时,res[2][3]=Math.max(res[2-1][3], res[2-1][3-3]+Value(2))
,Value(2)表示2号物品的价格,该式左半部分表示不选择2号物品(只能选1号),右半部分表示剩余空间为3,选择2号物品后,虽然还可选一个物品,但没有空间剩余,记得加上2号的价格。
只是这样讲确实没什么意思,但后来我重新看了一遍该算法后,不知道你们有没有和我一样的发现:在我们自下而上逐步填表的时候,往往只需要知道其上一行的内容就足够解决问题!如下:
res[m][n]=(n<ws[m]) ? res[m-1][n] : Math.max(res[m-1][n], res[m-1][n-ws[m]]+vs[m]);
解释:
我们在之前用ws和vs存储0~4号物品的质量和价格(0号物品的质量价格均为0,0号物品的添加理由同5*11列表的构建),m和n表示各自所在m行n列。
在我们给res[m][n]赋值的时候,根据上面的代码,我们只用到了res[m-1]行的内容,那么,我们完全没必要创建二维数组啊。
原代码:
package KnapsackProbleminDynamicProgramming;