1. 程式人生 > 實用技巧 >多重揹包與二進位制優化

多重揹包與二進位制優化

一個容量為m的揹包,a個重量為 w [ i ] ,價值為 v [ i ] ,數量為 s [ i ] 的物品,求解最大價值方案。

(千萬別想:每次 s [ i ] - 1 。這是對於動態規劃的錯誤理解。)

/******************************************************************************************************************************************************************************************/

多重揹包問題:

這種問題其實是01揹包的變形:對於第 i 種物品,可以裝 j 個( 0 ≤ j ≤ s [ i ] )

for(int i=0;i<a;i++)
        for(int j=m;j>=w[i];j--)
            for(int k=1;k*w[i]<=j&&k<=s[i];k++)
                dp[j]=max(dp[j],dp[j-k*w[i]]+k*v[i]);

時間複雜度為o(m*∑s)

/********************************************************************************************************************************************************************************************/

多重揹包的二進位制優化:

樸素的迴圈中,對於每一種物品,第三層迴圈大大增加了時間複雜度。

注意到這樣一件事情:任意正整數 n ,從1到 n 這 n 個數可以被 1 , 2 , 4 , 8 , ... , 2 ^ (k-1) , n - (2 ^ k) + 1 (2 ^ (k+1) > n)這 k + 1 個數(即log(n)+1個數)加和得到。

所以,對於每一個原始的物品 i ,可以構建一個新的物品佇列 L,在對L進行01揹包的時候,就已經將對i的多重揹包考慮完畢。L中的每一項與i有一個係數關係,就是上述那 k + 1 個數。這就是用二進位制思想進行了優化。複雜度大大降低。

for(int
i=0;i<l;i++) //l為新構建的物品總數 for(int j=m;j>=weight[i];j--) //weight和value中已經對應的乘好了係數 dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);

時間複雜度為o(m*log(∑s)) (?)