分支限界法:最優裝載問題
阿新 • • 發佈:2019-02-04
分支限界法的基本思想:
1)佇列式(FIFO)式分支限界法
佇列式分支限界法將活節點組織成一個佇列,並按照佇列“先進先出”的原則,選取下一個節點為當前拓展節點
2)優先佇列式分支限界法
優先佇列的分支限界法將活動表組織成一個優先佇列,並按照佇列規定的節點優先順序選取最高的下一個節點成為當前拓展節點
eg:基於FIFO式分支限界法的最優裝載問題
基本程式碼思路:
1:和回溯法的思路一樣,用FIFO分支搜尋所有的分支,並記錄以搜尋分支的最優解,搜尋完子樹也就找出了問題的最優解(遍歷更新bestW過程)
2:要求出最優解,必須搜尋到葉節點,當層數為n+1是,代表搜尋完所有的節點,搜尋結束
3
4:更新當前的bestW
public class BranchLimitFIFOSearch {
private int n;//貨箱數目
private float c1;
private float c2;
private float bestw;//第一艘船最優載重量
private float ew=0;//當前載重量
private float[] w;//貨物質量陣列
private float s=0;//所有貨箱的重量之和
private MyQueue mq=new MyQueue();//FIFO佇列
private float [] r;//r[i]表示w[i]貨物之後剩餘的貨物總重量
public static void main(String[] args) {
int n = 3;
float c1 = 50;
float c2 = 50;
float[] w = { 0, 10, 40, 40 };
float[] r={0,0,0,0};
BranchLimitFIFOSearch bfis = new BranchLimitFIFOSearch(n, c1, c2, w,r);
float s = bfis.getS();
if (s <= c1 || s <= c2) {
System.out.println("need only one ship!");
}
if (s > c1 + c2) {
System.out.println("no solution!,because s>c1+c2");
return;
}
bfis.maxLoading(c1);
float bestw = bfis.getBestw();
if (s - bestw <= c2) {
System.out.println("The first ship loading " + bestw);
System.out.println("The second ship loading " + (s - bestw));
} else {
System.out.println("no solution!,because s-bestw<=c2");
}
}
public BranchLimitFIFOSearch(int _n, float _c1, float _c2, float[] _w,float[] _r) {
n = _n;
c1 = _c1;
c2 = _c2;
w = _w;
r=_r;
for (float f : _w) {
s += f;
}
}
public float maxLoading(float c) {
r[w.length-1]=0;
for(int i=w.length-2;i>=0;i--){
r[i]=r[i+1]+w[i+1];
}
mq.put(new Float(-1)); // 初始化結點佇列,標記分層 ,當元素的值為-1時候,表示已經達到空間書的同一層節點尾部
int i = 1; // 結點的層
ew = 0; // 當前船的裝載量
bestw = 0; // 目前的最優值
while (!mq.empty()) { // 搜尋子集空間樹
if (ew + w[i] <= c) { // 檢查E-結點的左孩子,貨箱i是否可以裝載
addLiveNode(ew + w[i], i); // 貨箱i可以裝載
}
if((ew+r[i])>bestw){
addLiveNode(ew, i); // 右孩子總是可行的,不裝載貨物i ,當前路徑無法取代bestW
}
ew = (Float) mq.get(); // 取下一個結點
if (ew == -1) { // 到達層的尾部
if (mq.empty()) {
return bestw;
}
mq.put(new Float(-1));
ew = (Float) mq.get(); // 取下一個結點
i++; // ew的層
}
}
return bestw;
}
public void addLiveNode(float wt, int i) {//將當前載重兩新增入佇列
if (i == n) { // 是葉子
if (wt > bestw) {
bestw = wt;
}
} else { // 不是葉子
mq.put(new Float(wt));
}
}
public int getN() {
return n;
}
public void setN(int n) {
this.n = n;
}
public float getC1() {
return c1;
}
public void setC1(float c1) {
this.c1 = c1;
}
public float getC2() {
return c2;
}
public void setC2(float c2) {
this.c2 = c2;
}
public float getBestw() {
return bestw;
}
public void setBestw(float bestw) {
this.bestw= bestw;
}
public float getEw() {
return ew;
}
public void setEw(float ew) {
this.ew = ew;
}
public float getS() {
return s;
}
public void setS(float s) {
this.s = s;
}
}
import java.util.LinkedList;
public class MyQueue {
private LinkedList ll = new LinkedList();
public void put(Object o) {
ll.addLast(o);
}
public Object get() {
return ll.removeFirst();
}
public boolean empty() {
return ll.isEmpty();
}
}