优先队列式分支限界法 解装载问题

继续学习装载问题

上一篇我们学习了用队列式分支限界法求解,这一次采用优先队列式分支限界法来求解。
有一批共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

 

    原文作者:分支限界法
    原文地址: https://blog.csdn.net/redredxcar/article/details/85322597
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞