五大算法之分支定界法

问题:有一批共n个集装箱要装上2艘载重量分别为c1,c2的轮船,其中集装箱i的重量为wi,且要求确定是否有一个合理的装载方案可将这n个集装箱装上这2艘轮船。

抽象:将n个物品放到2个容器中,每个容器不能超重,寻找一个可行的方案。

思路:先尽可能的将第一艘船装满,然后将剩余的集装箱装到第二艘船上,如果第二艘船装不下则问题无解。则问题转化为求第一艘船最大装载量。使用分支定界法进行解空间搜索。

代码如下:

package test;
 
import java.util.LinkedList;
 
/**
 * 用分支定界法求装载问题
 * 
 * @author yanghang
 *
 */
public class Fenzhidingjie {
 
    private static float[] w = { 40, 40, 10 }; // 货箱质量数组
    private static int n = w.length; // 货箱数量
    private static float c1 = 50; // 第一艘船的载重量
    private static float c2 = 50; // 第二艘船的载重量
 
    private static float bestw; // 第一艘船的最大装载
    private static float ew; // 当前船的装载量
    private static LinkedList<Float> mq = new LinkedList<Float>(); // FIFO队列
 
    /**
     * 最优装载值
     * 
     * @param c
     */
    public static float maxLoading(float c) {
        mq.addLast(new Float(-1)); // 初始化结点队列,标记分层
        int i = 0; // E-结点的层
        ew = 0; // 当前船的装载量
        bestw = 0; // 目前的最优值
 
        while (!mq.isEmpty()) { // 搜索子集空间树
            if (ew + w[i] <= c) { // 检查E-结点的左孩子,货箱i是否可以装载
                addLiveNode(ew + w[i], i); // 货箱i可以装载
            }
 
            addLiveNode(ew, i); // 右孩子总是可行的,不装载货物i
 
            ew = (Float) mq.removeFirst(); // 取下一个结点
 
            if (ew == -1) { // 到达层的尾部
                if (mq.isEmpty()) {
                    return bestw;
                }
                mq.addLast(new Float(-1));
                ew = (Float) mq.removeFirst(); // 取下一个结点
                i++; // ew的层
            }
        }
        return bestw;
    }
 
    /**
     * 入队
     * 
     * @param wt
     * @param i
     */
    public static void addLiveNode(float wt, int i) {
        if (i == n - 1) { // 下标从0开始,是叶子
            if (wt > bestw) {
                bestw = wt;
            }
        } else { // 不是叶子
            mq.addLast(new Float(wt));
        }
    }
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        // 所有货箱的重量之和
        float s = 0;
        for (float f : w) {
            s += f;
        }
        if (s <= c1 || s <= c2) {
            System.out.println("need only one ship!");
        }
        if (s > c1 + c2) {
            System.out.println("no solution!");
            return;
        }
 
        float bestw = Fenzhidingjie.maxLoading(c1);
 
        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!");
        }
 
    }
 
}

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