1. 程式人生 > 其它 >SICP 2.2: 層次性資料和閉包性質(Python實現)

SICP 2.2: 層次性資料和閉包性質(Python實現)

有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 }