先举一个很通俗易懂的例子,也是图解算法中的例子,有一个只能装4kg的包,物品有音响3000元-重4kg,吉他1500元-重1kg,电脑2000元-重3kg。问,要想包里的价值最高,应该怎么装?(注意:不考虑 物品的体积,不要想吉他很大放不下。)算法
相信这个例子,随便看一下就能够知道要装什么,确定是装电脑加吉他。总价值3500块,又恰好4kg。segmentfault
拜托,这么简单的题目,看一眼就知道为何了。由于其他的组合状况,不可能比这个价值高的,即便比这个价值高,那也放不下了。很好,这就是最简单的暴利穷举算法了。红色的状况是超重了,放不下。学习
也就是说,物品数目是3的时候,有2^3种状况,而后找到符合条件的,也就是背包放的下的状况,取出价值最大的组合便可。 那么假如是4种商品呢,或者5种呢?这种组合状况是否是分别为2^4 2^5种,就很难一眼看出结果了吧,虽然上述逻辑对,可是这种 2^n 指数的量级 ,也未免也太复杂了。spa
上一篇动态规划入门的文章里有写过,动态规划,就是大事化小,小事化了。那么对于这种类型的题目,要怎么化繁为简呢?要怎么找出有表明性的模型呢?3d
现有背包载重量为4kg,这个背包已经装了现有状况下价值最高的物品,价值为v1。那么,在这个状况下,有一个新的物品,这个物品的重量是x kg,价值是v,那么此时对于这个4kg的包,装物品的最大值,分几种状况呢?code
有一个载重量是10kg 的背包,有五个物品,a 2kg 6元,b 2kg 3元,c 6kg 5元,d 5kg 4元,e 4kg 6元。问怎么放物品,价值最高?cdn
根据上面的推导,我来画一些表格blog
结合以前推导的结论,来以2kg那一列说明一下,第一个6元,是只有a物品时候,那么此时能放进背包的最高价值就是6元。当有了b物品能够选择时,有两种状况,(1)放进b物品,包的载重量-b物品重量后为0,而后加上b物品价值是3元(2)不放b物品原来价值是6元,取最大,即6元。get
随便抽出1个节点的值来验证一下吧:it
7kg时候,已经从abcd挑选结束,如今要考虑新增e的状况。 那个一直7kg时候,最高价值10元,新增的物品e是4kg,假如放了e,那么剩余空间是3kg,由图可知,在没有e以前,3kg的包最大能放6元物品。e的价值是6元,因此加起来12元,大于以前的最高值10元,因此对应的左标填值12元
//by 司徒正美
function knapsack(weights, values, W){
var n = weights.length -1
var f = [[]]
for(var j = 0; j <= W; j++){
if(j < weights[0]){ //若是容量不能放下物品0的重量,那么价值为0
f[0][j] = 0
}else{ //不然等于物体0的价值
f[0][j] = values[0]
}
}
for(var j = 0; j <= W; j++){
for(var i = 1; i <= n; i++ ){
if(!f[i]){ //建立新一行
f[i] = []
}
if(j < weights[i]){ //等于以前的最优值
f[i][j] = f[i-1][j]
}else{
f[i][j] = Math.max(f[i-1][j], f[i-1][j-weights[i]] + values[i])
}
}
}
console.log(f)
return f[n][W]
}
var a = knapsack([2,2,6,5,4],[6,3,5,4,6],10)
console.log(a)
复制代码
最终打印的结果以下
(但愿本身能一直坚持下去吧~~)