1. 程式人生 > >【經典動態規劃問題】0-1揹包問題

【經典動態規劃問題】0-1揹包問題

0,1揹包問題

一個揹包有一定的承重cap,有N件物品,每件都有自己的價值,記錄在陣列v中,也都有自己的重量,記錄在陣列w中,每件物品只能選擇要裝入揹包還是不裝入揹包,要求在不超過揹包承重的前提下,選出物品的總價值最大。

每個物品只有1個,給定物品的重量w價值v及物品數n和承重cap。請返回最大總價值。

狀態dp[i][j]  儲存物品0,...i儲存到承重為j的揹包中的最大價值

邊界討論:

當i等於0時,也就是說只有一個物品,重量為w[0],價值為v[0],那麼只有當j>= w[0]時,dp[0][j] = v[0];

當j等於0時,即揹包承重為0,不可能裝下任何物品,此時dp[i][0] = 0;

一般性的狀態討論:

對於當前的物品i,如果把這個物品裝入揹包(承重為j),揹包裡物品總價值是多少?

等於0,...i-1件物品的最大總價值+當前物品價值 也就是dp[i-1][j-w[i]]+v[i],注意此時留給0,...i-1物品的揹包承重為j-w[i],因為已經確定取索引為i的物品,這個物品會佔據w[i]的重量。

如果不裝入揹包(承重為j),揹包裡物品總價值為dp[i-1][j],也就是0,....i-1件物品放入承重為j的最大價值。

class Backpack {
public:
    int maxValue(vector<int> w, vector<int> v, int n, int cap) {
        // write code here
        int dp[500][500] = {0};//dp[i][j]指的是0,...i件物品,裝到j承重的包中的最大價值
        for(int k = 0;k <=cap;k++){//i = 0,只有第一件物品時,每件物品只有一個
            if(k>=w[0])//k表示容量
                dp[0][k] = v[0];
        }
          for(int i = 0;i<n;i++){//j = 0,承重為0時
            dp[i][0] = 0;
        }
        for(int i = 1;i<n;i++){
           for(int j = 1;j<=cap;j++){
               if(j>=w[i])//剩餘承重可以放w[i]
                  dp[i][j] = (dp[i-1][j-w[i]]+v[i])> dp[i-1][j]?(dp[i-1][j-w[i]]+v[i]):dp[i-1][j];
               else
                  dp[i][j] = dp[i-1][j];
           }
        }
        return dp[n-1][cap];
    }
};

注意初始化時0-1揹包問題的限定,即當只能取第一件物品時,j>w[0]的所有情況都是一樣的,即揹包中只能放下一件物品。