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

装载问题

有一批共n个集装箱要装上2艘载重量分别为c1,c2的轮船,其中集装箱i的重量为wi,且要求确定是否有一个合理的装载方案可将这n个集装箱装上这2艘轮船。
可证明,采用如下策略可以得到一个最优装载方案:先尽可能的将第一艘船装满,其次将剩余的集装箱装到第二艘船上。

其实质是要求第一艘船的最优装载。 其解空间树是一棵子集树。

《算法设计与分析》-王晓东著 一书P159中给出的java算法是不完全正确的。自然语言表达中,已知具有n个元素输入的解空间树的层数是n+1。 其算法用n表示解空间树的层数,但在maxLoading算法的初始化阶段  有代码 n = w.length -1  (w的定义int[ ] w, 表示输入集装箱的重量数组),且解空间树层循环变量i 初始化为1 。若输入数组w 元素为3, 则此处初始化后n= 3-1 = 2; java数组的索引是从0开始的,故w[0]的数据不会被处理,只有i=1和i=2的两层数据会被处理,导致算法无法得到正确运行结果;

我对该算法的修订版本如下: 

package ch06.book;

import java.util.LinkedList;
import java.util.Queue;


public class FIFOBBLoading {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] weight = {10,40,40};
		int capacity = 50;
		
		maxLoading(weight, capacity);
		System.out.printf("the best load weight is: %d", bestWeight);
	}

	static int n;
	static int bestWeight; // current max load;
	static Queue<Integer> queue;   // queue for living nodes;
	
	public static int maxLoading(int []containerWeight , int capacity) {
		// initialization 
		n = containerWeight.length-1 ;
		bestWeight = 0;
		queue = new LinkedList<Integer>();
		queue.offer(new Integer(-1));
		
		int i = 0;     // represent the node level of current expand node;
		int expandWeight = 0;   // the weight of load at the expand node;
		
		
		// search the binary solution space tree;
		while (true) {
			// check left child node;
			System.out.printf("checking left child, trying weight:%d \r\n", expandWeight + containerWeight[i]);
			if (expandWeight + containerWeight[i] <= capacity) {
				// the overall weight include left child node is less than capacity, 
				// then put the left child node in queue;
				System.out.printf("try put left child in queue, level %d \r\n", i);
				enQueue(expandWeight + containerWeight[i], i);
			}
			// right child node is always feasible;
			System.out.printf("try put right child in queue, level %d \r\n", i);
			enQueue(expandWeight, i);
						
			expandWeight = ((Integer)queue.poll()).intValue();
			System.out.printf("pop out the first element at queue head, expandWeight: %d \r\n", expandWeight);
			if (expandWeight == -1) {
				// reach the end of nodes of same level;
				if (queue.isEmpty())
					return bestWeight;
				queue.offer(new Integer(-1)); // add a mark node that represent the end of nodes of same level
				System.out.println("add level end mark ");
				
				expandWeight = ((Integer)queue.poll()).intValue();
				System.out.printf("pop out the first element at queue head, expandWeight: %d, then go to next level \r\n", expandWeight);
				i ++;   // go to next level;
			}
		}
	}
	
	public static void enQueue(int currentWeight, int i) {
		// put the living node into living node queue;
		if (i == n) {
			// this node is leaf node;
			if (currentWeight > bestWeight) {
				// found a better solution;
				bestWeight = currentWeight;
				System.out.printf("find current best load %d, node level is %d \r\n", bestWeight, i);
			}
		}
		else {
			// not leaf node;
			queue.offer(new Integer(currentWeight));
			System.out.println("DO put the child node in queue");
		}
	}
}

从main 方法的测试输入 weight = {10,40,40}, capacity = 50 ,可以求解出第一艘船最佳装载是50 , 与手动计算结果一致。

the best load weight is: 50

猜你喜欢

转载自blog.csdn.net/redredxcar/article/details/85305112
今日推荐