兩艘貨船載重 C1、C2,N 個貨箱重量 W[i],總重 ≤ C1+C2。求是否存在裝載方案使所有貨箱上船,若有輸出一種方案。
因總重 ≤ C1+C2,只需找到一個子集裝入船 1 使其重量 ≤ C1,剩餘自動 ≤ C2。即在 [0, C1] 範圍內尋找可行子集和。
每個貨箱兩種選擇:裝入船 1 (左分支, 1) 或不裝 (右分支, 0)。N 個貨箱構成高度 N 的二叉樹,葉子節點對應所有 2^N 種裝載方案。遍歷根到葉路徑即可得到一種選擇。
將選擇方案編碼為 N 位整數 mask (0 ~ 2^N-1):
i 位為 1 → 第 i 個貨箱裝入船 1mask 從 2^N-1 遞減至 0mask 並累加對應重量C1 立即跳出內層循環#include#include void search(int *weights, int n, int C1, int C2) { int total = 0; for (int i=0; i = 0; mask--) { int sum = 0; for (int i = 0; i < n; i++) { if (mask & (1 << i)) { sum += weights[i]; if (sum > C1) { sum = -1; break; } // 剪枝 } } if (sum >= 0 && sum <= C1 && (total - sum) <= C2) { printf("方案 mask=%x: ", mask); for (int i=0; i 複雜度分析
- 時間:
O(N * 2^N),N ≤ 20可接受,N > 25需動態規劃/分支限界- 空間:
O(N)進階優化方向
- 動態規劃:
dp[w]記錄達到重量w的方案掩碼,O(N*C1),適用大N小C1- 分支限界:按重量降序排列,計算剩餘最大可能和剪枝
- 會合中間:
N=40時分兩半各2^20枚舉,再雙指針合併