“特殊”0-1揹包問題

引言

對於通常的0-1揹包問題來說,只用考慮重量以及放與不放這兩個因素,今天看到一道問題加入了對於體積因素的考慮,即最終結果要求重量體積都不大於要求的值,且價值最大。
原題如下:
小劉去春遊,有5個物品,已知各物品的質量、體積、個數、價格(各項數值可以自己找一組帶一下,思想都是一樣的),總共能帶500cm³和100kg的物品,求能帶物品的最大價值。請用遞歸算法解決。

遞歸解法

很明顯這是在經典的0-1揹包問題上加了個干擾條件,其實如果真的完全瞭解0-1揹包的話就會發現其實本質都是一樣的,不過是填格子,做選擇,最後組合成找出最優解而已。
經典的0-1揹包遞歸式子k如下所示:

假設c[i,w]代表揹包中物品爲i個且揹包承載重量爲w時的最大價值。那麼對於每一個物品,是否要放入揹包就可以寫作如下遞歸式子:(vi表示當前物品價值)


c[i,w] = c[i-1][w] > c[i-1][w-wi]+vi ?c[i-1][w]:c[i-1][w-wi]+vi;

那麼現在加入一個體積因素這個式子就可以寫成:

假設c[i,w,v]代表揹包中物品爲i個且揹包承載重量爲w,體積爲v時的最大價值。那麼對於每一個物品,是否要放入揹包就可以寫作如下遞歸式子:(bi表示當前物品價值)
c[i,w,v] = c[i-1][w][v] > c[i-1][w-wi][v-vi]+bi ?c[i-1][w][v]:c[i-1][w-wi][v-vi]+bi;

ok,既然遞推式子出來了,那麼遞推函數代碼也就呼之欲出了。在此以java舉例

public class Main{
 static int W = 100;
 static int number = 5;
 static int V = 500;
 static int VALUE[] = {60, 20, 10, 60, 100};
 static int WEIGHT[] = {20, 30, 50, 60, 80};
 static int CAPACITY[] = {68,100,200,30,340};
 public static void main(String[] args)
 {
        int maxValue = calculate(number-1, W,V);
        System.out.println(maxValue);
 }
public static int calculate(int i, int j , int k)
{
        int r1 = 0;
        int r2 = 0;
        int r = 0;

        if (i == -1)
        {
                return 0;
        }

        if(j >= WEIGHT[i] && k >= CAPACITY[i])
        {
                r1 = calculate(i-1,j - WEIGHT[i],k-CAPACITY[i]) + VALUE[i];
                r2 = calculate(i-1,j,k);
                r = (r1>r2)?r1:r2;
        }

        return r;
}

}

從遞歸角度看,其實和經典0-1揹包差不多,無非是在遞歸判斷式,多加個判斷而已,但是如果換成非遞歸算法那就是相當於一個3*3的填格子問題了。不過問題本質沒有改變,依然是擁有多個交叉子問題,然後做選擇,將一系列子問題遞推最終得出最優解的過程,即動態規劃的經典思路。
ok,好久沒更新寫過博客類的東西了,發現了這個問題感覺回想起大學寫上算法課的思考過程,特此記錄一下,順帶複習下0-1揹包。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章