先舉一個很通俗易懂的例子,也是圖解算法中的例子,有一個只能裝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)
複製代碼
最終打印的結果以下
(但願本身能一直堅持下去吧~~)