分支限界法
分支限界搜尋,以廣度優先或最小耗費優先的方式搜尋解空間。
這裡直接是用的fifo。
其選擇下一擴充套件結點的策略是:在每乙個活結點處,計算乙個函式值(限界),並根據函式值,從當前活結點表中選擇乙個最有利的結點作為擴充套件結點,使搜尋朝著解空間上有最優解的分支推進,以便盡快地找出乙個最優解。
針對01揹包問題,需要確定乙個上界函式,見**。
對於每乙個非葉活結點,其左孩子表示裝入下乙個物品,則需要判斷是否會超出揹包容量;對於其右孩子(不裝入下乙個物品)來說,一定不會超出揹包容量,但是可以對其做約束來剪枝,僅當往下發展會有更大上界時才將其加入。
源**:
public
findmax3()
queue =
newlinkedlist
();//初始化
cur_value =0;
cur_weight =0;
best =0;
}//求上界
public
float
maxbound
(int t)
//剩餘容量已經放不下第t個物品了,計算上界
if(treturn bound;
}//加入可行結點
private
void
addlivenode
(float upper,
float curvalue,
float curweight,
int level)
}private
float
knapsack()
addlivenode
(upbound, cur_value+value[i]
, cur_weight+weight[i]
, i+1)
;}//右節點一定是不超過limit的,對它做約束,僅當往下發展有可能有更大上界的時候才加入
upbound =
maxbound
(i+1);
if(upbound >= best)
system.out.
println
(queue.
size()
);if(queue.
isempty()
)
heapnode node = queue.
peek()
; queue.
poll()
; cur_value = node.value;
cur_weight = node.weight;
upbound = node.upbound;
i = node.level;
}}
回溯法
回溯法其實思想跟分支限界很像,選擇下乙個擴充套件結點的策略也基本相同,但是回溯法是深度優先搜尋的,這裡用的遞迴版。回溯法可以輸出所有符合條件的解,而分支限界求解目標是最優解。
public
void
knapsack
(int k)
} system.out.
println
("該方案下裝入的價值為:"
+best_val)
;return;}
//左節點是否可行
if(current_wei+weight[k]
<=limit)
//右節點可能有更大的上界才加入if(
maxbound
(k)>best_val)
}
分支限界法解決0 1揹包問題
0 1揹包問題我們已經說過很多次了,這次是用最近學的分支限界法解決。分支限界法就是利用佇列或者優先佇列在儲存解空間樹的活結點,並每次彈出乙個作為擴充套件結點,是一種廣度優先遍歷,區別於回溯法的深度優先遍歷。而優先佇列時間複雜度更低,因為我們每次加入乙個活結點時,佇列都會排序,所以我們出隊的結點一定是...
0 1揹包問題 分支限界法
0 1揹包問題可描述為 n個物體和乙個揹包。對物體i,其價值為value,重量為weight,揹包的容量為w 如何選取物品裝入揹包,使揹包中所裝入的物品總價值最大?2.1 用到的資料結構 class goods 定義貨物資料型別 class knapsack 揹包 2.2 演算法步驟1 定 空間。x...
分支限界法 0 1揹包問題
分支限界法類似於回溯法,也是在問題的解空間上搜尋問題解的演算法。一般情況下,分支限界法與回溯法的求解目標不同。回溯法的求解目標是找出解空間中滿足約束條件的所有解,而分支限界法的求解目標則是找出滿足約束條件的乙個解,或是在滿足約束條件的解中找出使某一目標函式值達到極大或極小的解,即在某種意義下的最優解...