继续学习装载问题
上一篇我们学习了用队列式分支限界法求解,这一次采用优先队列式分支限界法来求解。
有一批共n个集装箱要装上2艘载重量分别为c1,c2的轮船,其中集装箱i的重量为wi,且要求确定是否有一个合理的装载方案可将这n个集装箱装上这2艘轮船。
可证明,采用如下策略可以得到一个最优装载方案:先尽可能的将第一艘船装满,其次将剩余的集装箱装到第二艘船上。
其实质是要求第一艘船的最优装载。 其解空间树是一棵子集树。
《算法设计与分析》-王晓东著 一书P164-165给出的代码同样是存在问题,无法运行的。主要表现是MaxHeap的定义没有给出,循环变量i的初值是1,计算扩展结点相应载重量的for循环以及构造当前最优解的for循环中终止条件都没有考虑j=0的情况;
对代码的修订如下:
package ch06.book;
import java.util.PriorityQueue;
public class PiorityBBLoading {
static PriorityQueue<HeapNode> heap = null;
static int bestWeight = 0;
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] weight = {10,40,40};
int capacity = 50;
int [] bestSolution = new int[weight.length];
bestWeight = maxLoading(weight, capacity, bestSolution);
System.out.printf("the best load weight is: %d \r\n", bestWeight);
System.out.print("the node path of best solution:");
for(int i=0; i<bestSolution.length; i++) {
System.out.printf("\t%d", bestSolution[i]);
}
}
public static int maxLoading(int []containerWeight , int capacity, int[] bestSolution) {
// initialization
heap = new PriorityQueue<HeapNode>();
int n = containerWeight.length -1; // n+1 represents the number of boxes, equals with the number of tree levels;
BBNode expandNode = null;
int i = 0; // represent the node level of current expand node;
int expandWeight = 0; // the weight of load at the expand node;
// declare the remain weight array
int [] remains = new int[n +1];
remains[n] = 0;
// backward calculate the remain weight for each node;
for (int j = n-1; j>=0; j--) {
remains[j] = remains[j+1] + containerWeight[j+1];
}
// search the binary solution space tree until reach a leaf node;
// reach a leaf node when i = n+1;
while (i != n +1) {
// check left child node;
System.out.printf("checking left child, trying weight:%d + %d \r\n", expandWeight , containerWeight[i]);
if (expandWeight + containerWeight[i] <= capacity) {
// the overall weight include left child node is less than capacity, so left child is a feasible node;
// then put the left child node in queue;
int nodePriority = expandWeight + containerWeight[i]+ remains[i];
System.out.printf("try put left child in Heap: level %d, priorty: %d \r\n", i, nodePriority);
addLiveNode(nodePriority, i+1, expandNode, true);
}
// right child node is always feasible;
System.out.printf("try put right child in Heap: level %d, priorty: %d \r\n", i, expandWeight + remains[i]);
addLiveNode(expandWeight + remains[i], i+1, expandNode, false);
// retrieve next expand node;
HeapNode node = heap.poll();
i = node.level;
expandNode = node.liveNode;
expandWeight = node.upperLimitWeight - remains[i-1];
System.out.printf("get next expand node in Heap and process: level:%d, node weight: %d\r\n", i, expandWeight);
}
// build the best solution
for(int j = n; j>=0; j--) {
bestSolution[j] = expandNode.isLeftChild? 1:0;
expandNode = expandNode.parent;
}
return expandWeight;
}
public static void addLiveNode(int upLimit, int level, BBNode parent, boolean isLeft) {
// put this live node in to MaxHeap of live node;
BBNode b = new BBNode(parent, isLeft);
HeapNode node = new HeapNode(b, upLimit, level);
heap.add(node);
}
/**
* This internal class represent a solution space tree node;
* @author wanyongquan
*
*/
static class BBNode{
BBNode parent;
boolean isLeftChild;
BBNode(BBNode parent, boolean isLeft) {
this.parent = parent;
this.isLeftChild = isLeft;
}
}
/**
* This internal class represent a node in MaxHeap;
* @author wanyongquan
*
*/
static class HeapNode implements Comparable<HeapNode>{
BBNode liveNode;
int upperLimitWeight; // the upper limitation of live node;
int level; // the node level in solution space tree
public HeapNode(BBNode node, int upLimit, int level) {
this.liveNode = node;
this.upperLimitWeight = upLimit;
this.level = level;
}
public int compareTo(HeapNode otherNode) {
// notice the two params's order ;
// this will works as MaxHeap;
return Integer.compare( otherNode.upperLimitWeight, this.upperLimitWeight ) ;
}
public boolean equals(HeapNode item) {
return this.upperLimitWeight == ((HeapNode)item).upperLimitWeight;
}
}
}
main方法中测试的结果如下图所示,可以最优装载量和解空间树最优选择路径都是正确的。
the best load weight is: 50
the node path of best solution: 1 1 0