揹包問題(0/1揹包,完全揹包,多重揹包)

你的揹包讓我走得好緩慢,借了終於陪着我腐爛

1. 0/1揹包

有一個腐爛的揹包,容量爲v,現有n件物品,每件物品有兩個屬性,體積w,和價格p,我們要選擇物品往揹包裏放,使得在物品總容積不超過v的情況下價值最大。

思路:

1)我們只在乎某件物品放不放進揹包,而不在乎放進去的順序,因爲物品一樣,順序不一樣,結果相同。

2)我們從第一件物品開始考慮,只有兩種情況,放或不放,然後考慮第二件物品,放或不放,。。。。。。第n件物品放或不放。

3)放則記爲1,不放記爲0.那麼假如共4件物品,所有可能的情況爲0000,0001,0010,0011.....1111共16種情況。只要枚舉完這16種情況我們就知道最大價值是多少。

4)雖然上面說有16種情況,但實際上有些情況是不存在的,例如1111,放入第四個物品會超出揹包容量,所以應爲1110。

5)我們定義maxValue(n,v)爲容量爲v時,選取物品1~n中若干件所能得到的最大價值。我們從第n件到第1件物品一次判斷是否選取,每步都有下面的公式。不選maxValue(n-1,v),選maxValue(n-1,v-Vn)+Pn,取max

                                          0                                    1

---maxValue(n,v)=max(maxValue(n-1,v), maxValue(n-1,v-Vn)+Pn),

當第k件物品遇到Vrest<Vk那麼第k件物品只能不選取:

---maxValue(n,v)=maxValue(n-1,v)

這樣在邊界的時候我們是可以直接得出結果的,然後回溯得出maxValue(n,v)。

解法:

1)我們可以用遞歸函數來求,注意的是要用一個temp[n][v]數組存儲已經求過的maxValue(n,v)來避免重複計算,因爲到達狀態[n,v]的可能不止一種情況。

2)用動態規劃,遞歸是自頂向下,到達邊界在回溯,而動態規劃則是直接自底向上。

每個maxValue(n,v)關聯的狀態只有maxValue(n-1,v)或maxValue(n-1,v-Vn).所以我們我們填一個n+1行v+1列的表,從maxValue(0,0)一直到maxValue(n,v),一直迭代。詳細解釋見https://blog.csdn.net/qq_38410730/article/details/81667885

 

2. 完全揹包

在完全揹包中是不限制每件物品的數量的,而0/1揹包是每種物品只有一件。此時的問題不是針對每種物品放或不放(放0個或1個),而是放幾個的問題(放0個,1個,2個。。。。or n個),這裏物品i最多放maxSpace//vi件。因此我們在放每件物品的時候要多加一個循環,分別算出maxValue(i,v)在物品i取0至maxSpace//vi件時的值,取最大的作爲maxValue[i][v]的最終值。動態規劃填表一行一行的填。詳細見https://www.cnblogs.com/mfrank/p/10803417.html

 

3.多重揹包

每種物品的數量爲num[i]個,完全揹包的物品數是無限的,多重揹包是有限個。和完全揹包基本相同,核心是每種物品放幾個,從0~num[i], 個數不超過num[i]的同時空間也不能超過揹包容量,詳細見https://www.cnblogs.com/mfrank/p/10816837.html

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;


int main(){
    int space,kind;
    cin>>space>>kind;
    vector<vector<int>>data(kind+1,vector<int>(3,0));
    vector<vector<int>>dp(kind+1,vector<int>(space+1,0));

    //space  price  num
    //注意這裏是從1開始,只有物品1~kind,沒有物品0
    for(int i=1;i<kind+1;i++)cin>>data[i][0]>>data[i][1]>>data[i][2];

    for(int i = 1; i<kind+1;i++){
        for(int j=1;j<space+1;j++){
            for(int k=0;k<=data[i][2]&&j>=k*data[i][0];k++){//0表示不選,注意選的第i件物品總體積不超過當前的容量
                //由於這裏考慮的是選k件物品的數量,所有下面每次減掉的空間是k*data[i][0],增加的價值是k*data[i][1]
                    dp[i][j]=max(dp[i][j],dp[i-1][j-k*data[i][0]]+k*data[i][1]);
            }
        }
        

    return 0;
}











我不生產知識,我只是知識的搬運工------農夫

 

 

 

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