--- comments: true --- # 15.6   練習 ## 15.6.1   知識鞏固 ### 1.   每次選最大硬幣一定最好嗎 硬幣面值為 `[1, 7, 10]`,目標金額為 14。 1. 按“每次取不超過剩餘金額的最大面值”執行,寫出所取硬幣; 2. 是否存在使用更少硬幣的方案?如果存在,請寫出一種;如果不存在,請說明理由; 3. 這能否說明該貪婪策略對任意硬幣面值都正確? ??? success "參考答案" 1. 貪婪依次選擇 `10 + 1 + 1 + 1 + 1`,共 5 枚硬幣。 2. 存在使用更少硬幣的方案:`7 + 7`,只需 2 枚硬幣。 3. 不能。這個反例說明,對任意硬幣面值,每次選擇當前能取的最大面值並不一定得到最少硬幣數; 眼前最大的選擇可能破壞後續更好的組合。 ### 2.   背包應該先裝哪件物品 一個容量為 4 千克的背包中可以裝入以下物品,物品允許只取一部分, 所取價值與重量成正比: - 物品 A:重量 4 千克,價值 20; - 物品 B:重量 3 千克,價值 18。 1. 兩件物品每千克的價值分別是多少?應先裝哪一件? 2. 按分數背包的貪婪策略裝滿背包,最終價值是多少? 3. 在物品可以切分、背包限制總重量的情況下,選擇物品時應該比較總價值還是每千克價值?為什麼? ??? success "參考答案" 1. A 每千克價值為 `20 ÷ 4 = 5`,B 每千克價值為 `18 ÷ 3 = 6`, 因此應先裝單位價值更高的 B。 2. 先裝入全部 B,佔用 3 千克、獲得價值 18;剩餘 1 千克容量, 再裝入 1 千克 A,獲得價值 5。最終價值為 `18 + 5 = 23`。 3. 背包限制的是總重量,而且物品可以切分,所以應比較單位重量的價值。 A 的總價值雖然更高,但每千克價值低於 B;若先裝滿 A,只能得到價值 20。 ### 3.   兩個指標下一步怎樣移動 隔板高度為 `[1, 8, 6, 2, 5]`,用首尾雙指標尋找最大容量。 容量等於“兩塊隔板中較短者的高度 × 兩塊隔板的下標距離”。 1. 初始時左指標在下標 0、右指標在下標 4,當前容量是多少?下一步應移動哪個指標? 2. 按照第 1 問的選擇移動一次後,兩個指標分別位於哪個下標?此時容量是多少?下一步又應移動哪個指標? 3. 在當前一對隔板中,可以移動較短隔板對應的指標,也可以移動較長隔板對應的指標。哪一種移動仍有可能得到更大的容量?為什麼? ??? success "參考答案" 1. 當前容量為 `min(1, 5) × (4 - 0) = 4`。左側隔板較短,因此移動左指標。 2. 移動左指標後,兩個指標分別位於下標 1 和 4。當前容量為 `min(8, 5) × (4 - 1) = 15`。右側隔板較短,因此下一步移動右指標。 3. 移動較短隔板對應的指標,才仍有可能得到更大的容量。移動較長隔板後,兩塊隔板的距離一定縮短,而容器高度仍受未移動的短板限制, 只可能不變或變小。因此容量不可能超過移動前;只有移動短板,才有機會遇到更高的隔板。 ## 15.6.2   程式設計練習 ### 1.   分數背包 給定等長陣列 `wgt` 和 `val`,其中 `wgt[i] > 0`、`val[i] >= 0`,背包容量 `cap >= 0`。 每種物品只有一件,但允許只裝入其中一部分, 獲得的價值按所裝重量佔該物品總重量的比例計算。請使用貪婪演算法, 並以實數返回背包能夠獲得的最大總價值。 ??? tip "解題提示" 1. 先計算每件物品的單位重量價值 val[i] / wgt[i],除法結果要保留小數 2. 單位價值越高的物品越先裝入背包 3. 若剩餘容量小於當前物品重量,就裝入恰好填滿背包的部分並結束