在上一篇文章中,簡單分析了0-1揹包問題,這篇接着簡單分析下完全揹包問題。
完全揹包的問題形式如下:有一揹包,只能裝重量爲V的物品,有n個的物品,這些物體體積爲w,價值爲v,在每個物品最多可以裝無線個的情況下,怎麼裝物品可以讓揹包中的物品價值最大。完全揹包問題與0-1揹包相似,不同的是:0-1揹包問題彙總,每個物品最多隻能裝1個;而在完全揹包中,每個物品在不超過揹包限重的情況下,可以裝無數個。因此,完全揹包的分析思路與0-1揹包類似,不同之處在於狀態轉移公式的推導。
與0-1揹包問題分析類似,可以先定義一些變量,來輔助分析。具體爲:value[ i ]表示第i個物品的價值,weight[ i ]表示第i個物品的體積,dp[ j ]表示當前揹包容量爲j時,最佳組合對應的價值。爲方便分析,設定物品個數爲5,揹包重量限制爲20,示例數據如下:
體積(weight) | 2 | 3 | 4 | 5 | 9 |
價值(value) | 3 | 4 | 5 | 8 | 10 |
分析步驟如下:
1、如果按照上篇文章的方式做,構建一個二維數組,就需要三層for循環,肯定不是一個好的解決方法。此時可以用一維數組dp[ ]直接來存儲value,進而用兩層for循環解決該問題。
2、以dp[ j ],即揹包可裝重量爲j的狀態來進行分析(i爲物品種類)。此時可能進行的動作有如下幾種:
1>再裝入一件相同物品價值大,即dp[ j ] = dp[ j+1 ];
2>再裝入一件其他物品價值大,即dp[ j ] = dp[ j-weight[ i ] ] + value[ i ]。
尋找最大價值的過程,就是不斷更新dp數組的過程,直到數組中最後一個值填完,即最大value值。
Java代碼如下:
static int weight[ ]={0,2,3,4,5,9}; //每個商品容量
static int value[ ]={0,3,4,5,8,10}; //每個商品價值
static int NUM = weight.length; //商品種類。包含第0個這個特殊值
static int CAP = 21; //總可用容量+1,包含第0個這個特殊值,所以總容量是20
//不斷填充value數組
int dp[] = new int[ CAP ];
for(int i=1;i<NUM;i++){
for(int j=weight[ i ];j<CAP;j++){
dp[ j ] = Math.max(dp[ j ],dp[ j-weight[ i ] ]+value[ i ]);
}
}
//數組最後一個值,即爲最大value值
System.out.println(dp[ 20 ]);