0/1 背包問題要求你從不可分割的物品中,挑選最有價值的子集合,使其能放入一個單一整數容量限制內;每件物品只能用一次或完全不用,且最佳解是透過一個跨物品與容量單位的精確動態規劃表找到。 每列提供一個正整數重量與一個非負值;目標是在總重量不超過輸入容量的前提下,使總值最大化。「0/1」的標記是字面意義的——物品不會被切分、重複或部分裝入,且比容量重的物品會被拒絕,而不是悄悄地被排除。對這種有界情況精確求解,代表結果對於這些輸入而言是經過證明的最佳解,而不只是一個不錯的猜測。背包問題計算機在本機端執行那個精確的 0/1 動態規劃,並將選定的標籤、總值、已用重量與剩餘容量以可複製的純文字呈現。

how to solve knapsack problem
如何使用動態規劃求解背包問題

0/1 背包問題實際上在問什麼

經典的表述方式將一個容器視為一個純量容量,並將每個候選項目視為一個不可分割的選擇,附帶兩個數字——重量與價值。目標是最大化總值,限制條件是總重量維持在容量以內,而整數規則強制每個決策變數只能是 0 或 1。Google OR-Tools 將此描述為挑選一個總值最大化且不超過容量的子集合,這正是計算機所實作的同一個模型。

三個小細節決定了一個給定的問題是否符合 0/1 形式。第一,物品是不可分割的——沒有「拿半台伺服器」或「拿專案 30%」這種概念。第二,容器是一個單一純量限制,而不是一組等大的箱槽,所以多容器的問題需要不同的工具。第三,最佳解就是最高的總值;並沒有諸如「最小化浪費」之類的第二目標。當這三個細節都成立時,動態規劃方法會在有限的時間與記憶體內達到全域最佳解。

將容量與物品輸入計算機

第一個輸入是介於 1 到 10,000 之間的一個整數容量。容量與重量都必須是整數,因為動態規劃表會為每個容量單位保留一個狀態,小數的重量測量應在輸入前以一致方式放大——例如,把 2.5 公斤轉成 25 個十分之一公斤,同時須注意更細的刻度會讓表格變大。

每列物品包含三個以逗號分隔的部分:標籤、正整數重量、與一個值。由於逗號是用來分隔三個欄位的,所以標籤不能包含逗號,而重複的標籤會被拒絕,如此輸出才能避免以相同識別名稱命名兩個被選中的物品。比容量大的重量會在輸入時被拒絕而非被忽略,這讓「該列在當前限制下無法被視為可選候選」這件事變得明確。值可以是零或正的小數,也不必與重量使用同一單位——值可以是優先權點數、預期利潤,或任何你選擇的純量,只要值越大代表該物品在目標下越被偏好即可。

清單本身上限為 100 件物品,以保持瀏覽器記憶體與回應時間的可預測性,工具會直接拒絕空白欄位、非正數的重量、非有限的值,以及格式錯誤的列。設置這些輸入上限,是為了讓動態規劃表夠小,以便在同一個分頁內建立並回溯而不會卡住。

執行求解器並讀取每一個數字

  1. 在瀏覽器中開啟背包問題計算機;沒有任何資料會被上傳,表格是在你的分頁本機端建立的。
  2. 在表單頂端輸入那個單一整數容量——挑一個介於 1 到 10,000 之間、用來代表你單一容器的數字。
  3. 以標籤,重量,值的格式,將每件物品作為一列加入,重量保持為正整數,標籤不含逗號且不重複。
  4. 執行求解器,根據你的物品與容量建立 0/1 動態規劃表,並回溯所選的標籤。
  5. 檢視結果區塊:先讀取選定的物品,接著是其下方的總值、已用重量與剩餘容量。
  6. 若需要將選擇貼到工作表、簡報或作業報告中,可將選擇複製為純文字。
  7. 若你變更了標籤、重量、值或容量,請重新執行求解器;在等值的情況下,系統會保留較早出現的解,因此重複輸入會得到相同的答案。

動態規劃表如何達到最佳解

對於每一件物品以及從 0 到輸入上限的每一個容量,表格都會儲存「僅使用目前已考慮過的物品」所能達成的最佳總值。在每個儲存格中,它會比較兩個狀態:不加入該物品時的最佳值,以及把該物品加到先前相容狀態後的最佳值。兩者中較大的那一個會被保留,這就是 Stanford 的CS161 0/1 背包動態規劃課程中所描述的 0/1 形式標準遞迴。

表格建立完成後,求解器會從記錄下的決策往回走,以重建選定的標籤。在等值的情況下,較早的解會被保留,因此答案是確定性的:相同的輸入永遠會產生相同的輸出。八個經過人工稽核的黃金案例涵蓋精確裝滿、等值、平小數值、零值物品,以及一個眾所周知的陷阱——單純貪心地選擇最高「值對重量比」會錯過最佳解;例如,在容量為 10 的案例中,重量 4 / 值 40 加上重量 3 / 值 50 可達到值 90(總重量 7,遠低於容量 10),而非依循輸入順序或一個粗糙的比值順序。

變體物品規則容器求解器類型
0/1 背包(本工具)每件物品選一次或完全不選單一純量容量精確動態規劃
分數背包物品可被切分成多份單一純量容量依值對重量比的貪婪法
多重背包每件物品最多一次數個不同的容量精確整數規劃
裝箱問題每件物品一次,大小需放入箱中等大的箱,目標為最小化箱數啟發式(遞減首次適合)

這個表格清楚說明了為何同一套公式無法直接套用。貪婪的比值策略能解分數變體,但對 0/1 變體而言是可被證明錯誤的;而等大的箱把目標從「最大化值」變成「最小化使用的箱數」——這是一個不同的問題,需要由裝箱求解器來回答。

0/1 背包模型適用於哪些真實決策

課堂練習是顯而易見的用途,但只要有一個純量預算限制了多個不可分割的選擇,同樣的形式就會出現。以明確的人力預算進行功能優先排序、有界的投資組合範例、在人數上限內的專案選擇,以及小規模的配置草案,只要物品仍不可分割且限制仍為單一,都能清楚地對應到 0/1 形式。

一旦額外的結構進入問題,這個模型就會變得不足。計算機不知道實體尺寸、平衡性、易碎性、強制群組、不相容的配對、期限、風險或不確定性;一個數學上最佳化的純量選擇,在實體上仍可能不可行或在運作上不合適。對於財務投資組合、安全負載、醫療資源分配,或其他高風險的決策,純量模型本身並不足夠;在做出任何承諾之前,目標、相依性與限制條件應由負責任的審查者依據合適的領域模型進行檢視。

對於想要與貪婪變體做對比的讀者,分數背包逐步求解指南以允許物品切分的方式,示範了相同的形式,是個有用的健全性檢查,能說明為何在物品為 0/1 時,單純比值順序並不足夠。

想看更深入的內容,請參考如何解直角三角形的畢氏定理。