有n個貨櫃要裝上2艘載重量分別為c1和c2的輪船,其中貨櫃i的重量為wi,且
問題:
是否有乙個合理的裝載方案,可將這n個貨櫃裝上這2艘輪船?如果有,找出一種裝載方案。
例如:當n=3, c1=c2=50
(1)若w=[10, 40, 40]
可將貨櫃1和貨櫃2裝上第一艘輪船,而將貨櫃3裝上第二艘輪船;
(2)如果w=[20, 40, 40]
則無法將這3個貨櫃都裝上船;
已證明,如果乙個給定裝載問題有解,則採用下面的策略可得到最優裝載方案。
1.首先將第一艘輪船盡可能裝滿;
2.將剩餘的貨櫃裝上第二艘輪船。
將第一艘輪船盡可能裝滿等價於選取全體貨櫃的乙個子集,使該子集中貨櫃重量之和最接近c1。由此可知,裝載問題等價於以下特殊的0-1揹包問題。
用樹
表示解空間,則解為n元向量, xi∈ 。
約束條件:
當前搜尋的層i <= n時,當前擴充套件結點z為子集樹的內部結點,僅當滿足cw+w[i] <= c
時進入左子樹,x[i]=1; 當cw+w[i] > c
,在以結點z為根的子樹中所有結點都不滿足約束條件,因而該子樹中解都是不可行解,因而將在該子樹刪去。
限界函式:
由於是最優化問題, 可利用最優解性質進一步剪去不含最優解的子樹:
設z是解空間樹第i層上的當前擴充套件結點。
設 bestw: 當前最優載重量,
cw : 當前擴充套件結點z的載重量 ;
r : 剩餘貨櫃的重量;
在以z為根的子樹中任意葉結點所相應的載重量不超過cw + r。因此,當cw + r (限界函式) ≤ bestw時,可將z的右子樹剪去。即:cw + r > bestw 時搜尋右子樹,x[i]=0;
演示分析過程
;//搜尋子樹
if(cw+w[i]
<=c)
if(cw+r > bestw)
r+=w[i]
#include using namespace std;
int n; //貨櫃數
int cw; // 當前載重量, current weight
int bestw; //最優載重重量
int r; //剩餘貨櫃重量
int c1; //第一艘輪船的載重量
int c2; //第二艘輪船的載重量
int x[100]; //當前解
int bestx[100]; //當前最優解
int w[100]; //貨櫃重量陣列
void output()
return;
}r -= w[i];
if(cw + w[i] <= c1) //約束條件
if(cw + r > bestw) //限界函式
r += w[i];
}void initialize()
void input()
int main()
輸入請輸入箱子個數:4
請輸入兩艘船的最大載重量:100 100
請輸入箱子的重量:90 10 80 10
輸出
船1裝入的貨物為: 1 2
船2裝入的貨物為: 3 4
輸入
請輸入箱子個數:4
請輸入兩艘船的最大載重量:100 100
請輸入箱子的重量:90 20 90 10
輸出
不能裝入
裝載問題 回溯法
描述 有一批共n個貨櫃要裝上艘載重量為c的輪船,其中貨櫃i的重量為wi。找出一種最優裝載方案,將輪船盡可能裝滿,即在裝載體積不受限制的情況下,將盡可能重的貨櫃裝上輪船。輸入 由檔案load.in給出輸入資料。第一行有2個正整數n和c。n是貨櫃數,c是輪船的載重量。接下來的1行中有n個正整數,表示貨櫃...
回溯法 裝載問題
有n個貨櫃要裝上載重量為w的輪船,其中貨櫃i的重量為wi。不考慮貨櫃體積的限制,現在要將若干貨櫃裝上輪船,使他們的總重量為w,如果總重量相同要盡可能的使用少的貨櫃。有n個貨櫃要裝上載重量為c1 c2的輪船,其中貨櫃i的重量為wi。問兩艘輪船能否裝下所有貨櫃。深搜所有情況,重點是要剪枝。題目一剪枝條件...
裝載問題 回溯法
有一批共 n n n 個貨櫃要裝上艘載重量為 c c c 的輪船,其中貨櫃 i i i 的重量為 w i wi wi。找出一種最優裝載方案,將輪船盡可能裝滿,即在裝載體積不受限制的情況下,將盡可能重的貨櫃裝上輪船。第一行有 2 個正整數 n n n 和 c c c。n n n 是貨櫃數,c c c ...