http://blog.csdn.net/kangroger/article/details/38864689ios
在hihocoder上面的題目中看到的這個問題,總結一下。先看01揹包問題。算法
01揹包問題:一個揹包總容量爲V,如今有N個物品,第i個 物品體積爲weight[i],價值爲value[i],如今往揹包裏面裝東西,怎麼裝能使揹包的內物品價值最大?數組
看到這個問題,可能會想到貪心算法,可是貪心實際上是不對的。例如最少硬幣找零問題,要用動態規劃。動態規劃思想就是解決子問題並記錄子問題的解,這樣就不用重複解決子問題了。數據結構
動態規劃先找出子問題,咱們能夠這樣考慮:在物品比較少,揹包容量比較小時怎麼解決?用一個數組f[i][j]表示,在只有i個物品,容量爲j的狀況下揹包問題的最優解,那麼當物品種類變大爲i+1時,最優解是什麼?第i+1個物品能夠選擇放進揹包或者不放進揹包(這也就是0和1),假設放進揹包(前提是放得下),那麼f[i+1][j]=f[i][j-weight[i+1]+value[i+1];若是不放進揹包,那麼f[i+1][j]=f[i][j]。app
這就得出了狀態轉移方程:oop
f[i+1][j]=max(f[i][j],f[i][j-weight[i+1]+value[i+1])。測試
能夠寫出代碼測試:優化
在hihocoder上面還講到能夠進一步優化內存使用。上面計算f[i][j]能夠看出,在計算f[i][j]時只使用了f[i-1][0……j],沒有使用其餘子問題,所以在存儲子問題的解時,只存儲f[i-1]子問題的解便可。這樣能夠用兩個一維數組解決,一個存儲子問題,一個存儲正在解決的子問題。this
再進一步思考,計算f[i][j]時只使用了f[i-1][0……j],沒有使用f[i-1][j+1]這樣的話,咱們先計算j的循環時,讓j=M……1,只使用一個一維數組便可。spa
for i=1……N
for j=M……1
f[j]=max(f[j],f[j-weight[i]+value[i])
在看完01揹包問題,再來看徹底揹包問題:一個揹包總容量爲V,如今有N個物品,第i個 物品體積爲weight[i],價值爲value[i],每一個物品都有無限多件,如今往揹包裏面裝東西,怎麼裝能使揹包的內物品價值最大?
對比一下,看到的區別是,徹底揹包問題中,物品有無限多件。往揹包裏面添加物品時,只要當前揹包沒裝滿,能夠一直添加。那麼狀態轉移方程爲:
f[i+1][j]=max(f[i][j-k*weight[i+1]+k*value[i+1]),其中0<=k<=V/weight[i+1]
使用內存爲一維數組,僞代碼
for i=1……N
for j=1……M
f[j]=max(f[j],f[j-weight[i]+value[i])
和01揹包問題惟一不一樣的是j是從1到M。01揹包問題是在前一個子問題(i-1種物品)的基礎上來解決當前問題(i種物品),向i-1種物品時的揹包添加第i種物品;而徹底揹包問題是在解決當前問題(i種物品),向i種物品時的揹包添加第i種物品。
代碼以下: