SICP 2.2: 層次性資料和閉包性質(Python實現)
阿新 • • 發佈:2022-05-07
有N件物品和一個最多能背重量為W的揹包。第i件物品的重量是weight[i],得到的價值是value[i] 。每件物品都有無限個(也就是可以放入揹包多次),求解將哪些物品裝入揹包裡物品價值總和最大。
完全揹包和01揹包問題唯一不同的地方就是,每種物品有無限件。
01揹包和完全揹包唯一不同就是體現在遍歷順序上!!!!!
01揹包的核心程式碼:
1 for(int i = 0; i < weight.size(); i++) { // 遍歷物品 2 for(int j = bagWeight; j >= weight[i]; j--) { // 遍歷揹包容量 3 dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);4 } 5 }
01揹包內嵌的迴圈是從大到小遍歷,為了保證每個物品僅被新增一次。
而完全揹包的物品是可以新增多次的,所以要從小到大去遍歷,即:
1 // 先遍歷物品,再遍歷揹包 2 for(int i = 0; i < weight.size(); i++) { // 遍歷物品 3 for(int j = weight[i]; j <= bagWeight ; j++) { // 遍歷揹包容量 4 dp[j] = max(dp[j], dp[j - weight[i]] + value[i]); 5 6 } 7 }
注意:
- 在01揹包中,二維dp陣列的兩個for遍歷的先後循序是可以顛倒了,一維dp陣列的兩個for迴圈先後循序一定是先遍歷物品,再遍歷揹包容量。
- 在完全揹包中,對於一維dp陣列來說,其實兩個for迴圈巢狀順序同樣無所謂!因為dp[j] 是根據 下標j之前所對應的dp[j]計算出來的。 只要保證下標j之前的dp[j]都是經過計算的就可以了。
完全揹包先遍歷揹包在遍歷物品,程式碼如下:
1 // 先遍歷揹包,再遍歷物品 完全揹包 2 for(int j = 0; j <= bagWeight; j++) { // 遍歷揹包容量 3 for(int i = 0; i < weight.size(); i++) { // 遍歷物品 4 if (j - weight[i] >= 0) dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);5 } 6 cout << endl; 7 }