10、耗材推荐算法部分

入参依次分别为:
List<BoxInfo> boxInfoList,耗材集合
List<GoodsInfo> goodsInfoList,商品集合
Long timeout_per_trail,时间限制(暂时未用)
Integer maxTrail,最大线程(暂时未用)
Boolean isXiangZhuang,是否箱装
int buffer_auto_bag,自动打包时的袋装buffer
double Threshold_box,箱装自动打包优先阈值
double Threshold_bag,袋装自动打包优先阈值
int num_sup,一个袋子最多可拓展的类型数
int buffer,耗材buffer
  • 极端情况处理(商品集合为空或者耗材集合为空)
  • 耗材集合优先级排序(箱子按体积从小到大,袋子按面积从小到大)
  • 将自动打包耗材和手工打包耗材分开
  • 手工打包耗材数据预处理(调整至长>=宽>=高)
  • 商品数据预处理(调整至长>=宽>=高)
  • 把商品分流,分为4类(硬塞的、常规、异形、原包)
  • 原包异形包裹计算
  • 常规商品集合优先级排序(最长边从小到大)
  • 将自动打包商品和手工打包商品分开
  • 若满足自动打包则走自动打包逻辑
  • 常规计算逻辑
    • 无商品时直接返回
    • 若均为类缠绕膜耗材,则直接把所有商品打成一个包裹,耗材若唯一则推荐此耗材,若不唯一则不推荐
    • 若全部都为硬塞的商品则这些商品走常规推荐
    • 根据商品集合的特征分别走不通的算法模块
      • 商品数为1时,精确计算
      • 商品数为2时,精确计算
      • 商品数>=3时
        • 若箱装、品类唯一,五块逻辑
        • 袋子集扩充为箱子集
        • 常规启发式逻辑
  • 若存在硬塞的商品,则把其放入第一个包裹里,若无包裹则单独成一个包裹

算法架构流程

public static List<Package> getPackagePair(List<BoxInfo> boxInfoList, List<GoodsInfo> goodsInfoList,
                                               Long timeout_per_trail, Integer maxTrail, Boolean isXiangZhuang,
                                               int buffer_auto_bag, double Threshold_box, double Threshold_bag, int num_sup, int buffer)
            throws Exception {

        //极端情况(耗材集合为0或者商品集合为0)处理
        if(goodsInfoList.size() == 0){
            return new ArrayList<Package>();
        }else if(boxInfoList.size() == 0){
            List<Package> resPackageList = new ArrayList<Package>();
            Package temp_package = new Package();
            for (int i = 0; i < goodsInfoList.size(); i++) {
                temp_package.getGoods().add(new GoodsInfo(goodsInfoList.get(i)));
            }
            resPackageList.add(temp_package);
            return resPackageList;
        }

        //根据手工耗材类型对体积或面积进行排序,从小到大排
        if (isXiangZhuang) {
            V_box_sorting(boxInfoList);
        } else {
            S_box_sorting(boxInfoList);
        }

        //将自动打包耗材和手工打包耗材分开
        List<BoxInfo> boxInfoList_auto = new ArrayList<BoxInfo>();
        List<BoxInfo> boxInfoList_normal = new ArrayList<BoxInfo>();

        for (BoxInfo boxInfo : boxInfoList) {
            if (boxInfo.auto == 1) {
                boxInfoList_auto.add(boxInfo);
            } else {
                boxInfoList_normal.add(boxInfo);
            }
        }

        //手工打包耗材数据预处理
        //默认包装装时长大于等于宽大于等于高
        for (BoxInfo boxInfo : boxInfoList_normal) {
            int length = Math.max(boxInfo.Length, Math.max(boxInfo.Width, boxInfo.Height));
            int height = Math.min(boxInfo.Length, Math.min(boxInfo.Width, boxInfo.Height));
            int width = boxInfo.Length + boxInfo.Width + boxInfo.Height - length - height;
            boxInfo.Length = length;
            boxInfo.Width = width;
            boxInfo.Height = height;
        }

        //商品货物数据预处理
        //对货物尺寸排序,长大于等于宽大于等于高
        for (GoodsInfo goodsInfo : goodsInfoList) {
            double length = Math.max(goodsInfo.Length, Math.max(goodsInfo.Width, goodsInfo.Height));
            double height = Math.min(goodsInfo.Length, Math.min(goodsInfo.Width, goodsInfo.Height));
            double width = goodsInfo.Length + goodsInfo.Width + goodsInfo.Height - length - height;
            goodsInfo.Length = length;
            goodsInfo.Width = width;
            goodsInfo.Height = height;
        }


        //不考虑装载,直接硬塞的商品,放在第一个包裹里
        List<GoodsInfo> goodsInfoList0 = new ArrayList<GoodsInfo>();

        //根据flag筛选分流商品,1常规,2异形,3原包
        List<GoodsInfo> goodsInfoList1 = new ArrayList<GoodsInfo>();
        List<GoodsInfo> goodsInfoList2 = new ArrayList<GoodsInfo>();
        List<GoodsInfo> goodsInfoList3 = new ArrayList<GoodsInfo>();

        for (GoodsInfo goodsInfo : goodsInfoList) {

            if (goodsInfo.Length <= 10 || goodsInfo.Width <= 10 || goodsInfo.Height <= 10) {
                goodsInfoList0.add(new GoodsInfo(goodsInfo));
                continue;
            }

            if (goodsInfo.flag == 1) {
                //确定每一个商品在这组耗材下能够装下,装不下的当做异形处理
                if (suitable(boxInfoList_auto, boxInfoList_normal, goodsInfo, isXiangZhuang, buffer)) {
                    goodsInfoList1.add(new GoodsInfo(goodsInfo));
                } else {
                    goodsInfoList2.add(new GoodsInfo(goodsInfo));
                }
            } else if (goodsInfo.flag == 2) {
                goodsInfoList2.add(new GoodsInfo(goodsInfo));
            } else {
                goodsInfoList3.add(new GoodsInfo(goodsInfo));
            }
        }

        //异形、原包包裹计算
        List<Package> resPackageList_alien = Alien.alien(goodsInfoList2);
        List<Package> resPackageList_original = Original.original(goodsInfoList3);

        //初始化结果Package的List并把原包异形结果加入
        List<Package> resPackageList = new ArrayList<Package>();
        resPackageList.addAll(resPackageList_alien);
        resPackageList.addAll(resPackageList_original);

        //常规商品集GoodsInfoList1装载
        //对商品最长边进行排序,长的放前面,先装
        goods_edge_sorting(goodsInfoList1);

        List<GoodsInfo> goodsInfoList1_auto = new ArrayList<GoodsInfo>();
        List<GoodsInfo> goodsInfoList1_normal = new ArrayList<GoodsInfo>();

        for (GoodsInfo goodsInfo : goodsInfoList1) {
            if (goodsInfo.auto == 1) {
                goodsInfoList1_auto.add(new GoodsInfo(goodsInfo));
            } else {
                goodsInfoList1_normal.add(new GoodsInfo(goodsInfo));
            }
        }

        //优先看是否满足自动打包约束
        if (goodsInfoList1_auto.size() == 1 && goodsInfoList1_normal.size() == 0) {
            StackingAuto.auto(boxInfoList_auto, boxInfoList_normal, goodsInfoList1_auto, isXiangZhuang, resPackageList, buffer, buffer_auto_bag, Threshold_box, Threshold_bag);
            packageSummary(resPackageList);
            return resPackageList;
        }


        //其他情况走常规手工打包逻辑
        //无商品时直接返回
        if(goodsInfoList0.size() == 0 && goodsInfoList1.size() == 0){
            packageSummary(resPackageList);
            return resPackageList;
        }

        //手工打包前,检查耗材是否均为类缠绕膜耗材
        if(ismembrane(boxInfoList_normal)){
            Package temp_package = new Package();
            if (boxInfoList_normal.size() == 1){
                temp_package.setBox(new BoxInfo(boxInfoList_normal.get(0)));
            }
            for (int i = 0; i < goodsInfoList0.size(); i++) {
                temp_package.getGoods().add(new GoodsInfo(goodsInfoList0.get(i)));
            }
            for (int i = 0; i < goodsInfoList1.size(); i++) {
                temp_package.getGoods().add(new GoodsInfo(goodsInfoList1.get(i)));
            }
            resPackageList.add(temp_package);
            return resPackageList;
        }

        if(goodsInfoList1.size() == 0){
            for (int i = 0; i < goodsInfoList0.size(); i++) {
                goodsInfoList1.add(new GoodsInfo(goodsInfoList0.get(i)));
            }
            goodsInfoList0 = new ArrayList<GoodsInfo>();
        }

        //至此,isXiangZhuang决定知否箱装,boxInfoList_normal和bagList分别为箱装耗材和袋装耗材集合,GoodsInfoList1是待装商品集
        //resPackageList为异形原包形成的包裹集,清洗好了数据,开始分情况装载
        //1个和2个基本属于精确求解,3个以上启发式求解
        //3个以上如果商品类型唯一的话触发5块逻辑
        //剩下的情形是size大于等于3的情况,此时走以下常规流程

        Set<String> skuSet = new HashSet<String>();
        for (GoodsInfo goodsInfo : goodsInfoList1) {
            skuSet.add(goodsInfo.sku);
        }

        if (goodsInfoList1.size() == 1) {
            StackingSimple.size_1(boxInfoList_normal, goodsInfoList1, isXiangZhuang, resPackageList, buffer);

        } else if (goodsInfoList1.size() == 2) {
            StackingSimple.size_2(boxInfoList_normal, goodsInfoList1, isXiangZhuang, resPackageList, buffer);

        } else if (goodsInfoList1.size() >= 3 && isXiangZhuang && skuSet.size() == 1) {
            StackingSimple.one_sku_size_more(boxInfoList_normal, goodsInfoList1, resPackageList, buffer);

        } else if (goodsInfoList1.size() >= 3) {
            List<BoxInfo> bagList_normal = createBagList(boxInfoList_normal, num_sup);
            StackingHeuristic.size_more(boxInfoList_normal, bagList_normal, goodsInfoList1, isXiangZhuang, resPackageList, buffer);

        }

        //看是否存在礼品袋
        if(goodsInfoList0.size() > 0){
            //如果存在包裹,则把硬塞的商品放在第一个包裹里,否则新建包裹
            if (resPackageList.size() > 0) {
                for (int i = 0; i < goodsInfoList0.size(); i++) {
                    resPackageList.get(0).getGoods().add(new GoodsInfo(goodsInfoList0.get(i)));
                }
            } else {
                Package temp_package = new Package();
                if (boxInfoList_normal.size() == 1){
                    temp_package.setBox(new BoxInfo(boxInfoList_normal.get(0)));
                }
                for (int i = 0; i < goodsInfoList0.size(); i++) {
                    temp_package.getGoods().add(new GoodsInfo(goodsInfoList0.get(i)));
                }
                resPackageList.add(temp_package);
            }
        }

        packageSummary(resPackageList);
        return resPackageList;

    }

附1、耗材排序模块

static void V_box_sorting(List<BoxInfo> boxInfoList) {
        Collections.sort(boxInfoList, new Comparator<BoxInfo>() {
            @Override
            //-1优先,体积小的放前面
            public int compare(BoxInfo b1, BoxInfo b2) {
                int v1 = b1.Length*b1.Width*b1.Height;
                int v2 = b2.Length*b2.Width*b2.Height;

                if(v1 < v2) {
                    return -1;
                } else{
                    return 1;
                }
            }
        });
    }

    static void S_box_sorting(List<BoxInfo> boxInfoList) {
        Collections.sort(boxInfoList, new Comparator<BoxInfo>() {
            @Override
            //-1优先,面积小的放前面,面积相等时,长边小的放前面,再相等时看高
            public int compare(BoxInfo b1, BoxInfo b2) {
                int l1 = Math.max(b1.Length,Math.max(b1.Width,b1.Height));
                int h1 = Math.min(b1.Length,Math.min(b1.Width,b1.Height));
                int w1 = b1.Length+b1.Width+b1.Height-l1-h1;

                int l2 = Math.max(b2.Length,Math.max(b2.Width,b2.Height));
                int h2 = Math.min(b2.Length,Math.min(b2.Width,b2.Height));
                int w2 = b2.Length+b2.Width+b2.Height-l2-h2;

                if(l1*w1 < l2*w2) {
                    return -1;
                }else if(l1*w1 > l2*w2){
                    return 1;
                }else if(l1 < l2) {
                    return -1;
                }else if(l1 > l2){
                    return 1;
                }else if(h1 < h2){
                    return -1;
                }else{
                    return 1;
                }
            }
        });
    }

附2、常规商品在这组耗材下是否能装下(否的话作为异形处理)

    static Boolean suitable(List<BoxInfo> boxInfoList_auto, List<BoxInfo>boxInfoList_normal, GoodsInfo goodsInfo, Boolean isXiangZhuang, int buffer){

        Boolean code = false;

        if(goodsInfo.auto == 0){
            if(isXiangZhuang){
                for(BoxInfo b:boxInfoList_normal){
                    if(b.Length+buffer>=goodsInfo.Length && b.Width+buffer>=goodsInfo.Width && b.Height+buffer>=goodsInfo.Height){
                        code = true;
                        break;
                    }
                }
            }else{
                for(BoxInfo b:boxInfoList_normal){
                    if(b.Length+b.Height-goodsInfo.Height+buffer>=goodsInfo.Length && b.Width+b.Height-goodsInfo.Height+buffer>=goodsInfo.Width){
                        code = true;
                        break;
                    }
                }
            }
        }else{
            //自动包装时,不考虑buffer,在自动包装装不下时,考虑手动打包
            if(isXiangZhuang){
                for(BoxInfo b:boxInfoList_auto){
                    int length = Math.max(b.Length,Math.max(b.Width,b.Height));
                    int height = Math.min(b.Length,Math.min(b.Width,b.Height));
                    int width = b.Length+b.Width+b.Height-length-height;
                    if(length>=goodsInfo.Length && width>=goodsInfo.Width && height>=goodsInfo.Height){
                        code = true;
                        break;
                    }
                }
                if(!code){
                    for(BoxInfo b:boxInfoList_normal){
                        if(b.Length+buffer>=goodsInfo.Length && b.Width+buffer>=goodsInfo.Width && b.Height+buffer>=goodsInfo.Height){
                            code = true;
                            break;
                        }
                    }
                }
            }else{
                for(BoxInfo b:boxInfoList_auto){
                    int length = Math.max(b.Length,Math.max(b.Width,b.Height));
                    int height = Math.min(b.Length,Math.min(b.Width,b.Height));
                    int width = b.Length+b.Width+b.Height-length-height;
                    if(length+height-goodsInfo.Height>=goodsInfo.Length && width+height-goodsInfo.Height>=goodsInfo.Width){
                        code = true;
                        break;
                    }
                }
                if(!code){
                    for(BoxInfo b:boxInfoList_normal){
                        if(b.Length+b.Height-goodsInfo.Height+buffer>=goodsInfo.Length && b.Width+b.Height-goodsInfo.Height+buffer>=goodsInfo.Width){
                            code = true;
                            break;
                        }
                    }
                }
            }
        }

        return code;
    }

附3、异形计算模块

package com.jd.jingwei.algorithm.method_alien;

import com.jd.jingwei.basis.*;
import com.jd.jingwei.basis.Package;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Alien {

    static void goods_coefficient_package_sorting(List<GoodsInfo> goodsInfoList) {
        Collections.sort(goodsInfoList, new Comparator<GoodsInfo>() {
            @Override
            //-1优先,最长边大的放前面
            public int compare(GoodsInfo g1, GoodsInfo g2) {
                double c1 = g1.coefficient_package;
                double c2 = g2.coefficient_package;

                if(c1 > c2) {
                    return -1;
                } else{
                    return 1;
                }
            }
        });
    }

    //判断是否存在没有形成包裹的商品
    static Integer num_exist(List<Integer>Goods_used_state){
        Integer sum_state = 0;
        for(Integer i:Goods_used_state){
            sum_state += i;
        }
        return sum_state;
    }

    //把异形包裹里,每个包裹里商品的包裹系数打印出来
    public static void VCS(List<Package> resPackageList_alien){
        for(Package p:resPackageList_alien){
            System.out.print("[");
            for(GoodsInfo goodsInfo:p.getGoods()){
                System.out.print(goodsInfo.coefficient_package+" , ");
            }
            System.out.println("]");
        }
    }

    public static List<Package> alien(List<GoodsInfo> GoodsInfoList2){

        List<Package> resPackageList_alien = new ArrayList<Package>();

        //按包裹系数排序,大的放前面
        goods_coefficient_package_sorting(GoodsInfoList2);

        //Goods_used_state表示每个Good的使用状态
        List<Integer> Goods_used_state = new ArrayList<Integer>();
        for(GoodsInfo g:GoodsInfoList2){
            Goods_used_state.add(1);
        }

        //先把大于等于1的处理了
        for(int i = 0; i < GoodsInfoList2.size(); i++){
            if(GoodsInfoList2.get(i).coefficient_package >= 1){
                Package temp_package = new Package();
                temp_package.getGoods().add(new GoodsInfo(GoodsInfoList2.get(i)));
                Goods_used_state.set(i,0);
                resPackageList_alien.add(temp_package);
            }
        }

        while(num_exist(Goods_used_state) > 0){
            Package temp_package = new Package();
            double sum_coefficient = 0;
            for (int i = 0; i < GoodsInfoList2.size(); i++) {
                if(Goods_used_state.get(i) > 0 && sum_coefficient + GoodsInfoList2.get(i).coefficient_package <= 1){
                    temp_package.getGoods().add(new GoodsInfo(GoodsInfoList2.get(i)));
                    Goods_used_state.set(i,0);
                    sum_coefficient += GoodsInfoList2.get(i).coefficient_package;
                }
            }
            resPackageList_alien.add(temp_package);
        }

        VCS(resPackageList_alien);
        return resPackageList_alien;
    }

}

附4、原包计算逻辑

    public static List<Package> original(List<GoodsInfo> GoodsInfoList3) {

        List<Package> resPackageList_original = new ArrayList<Package>();

        HashMap<GoodsInfo, Integer> nums_sku = new HashMap<GoodsInfo, Integer>();
        for(GoodsInfo goodsInfo:GoodsInfoList3){
            if (nums_sku.get(goodsInfo) == null) {
                nums_sku.put(goodsInfo, 1);
            } else {
                nums_sku.put(goodsInfo, nums_sku.get(goodsInfo)+1);
            }
        }

        for(Map.Entry<GoodsInfo, Integer> entry: nums_sku.entrySet()){
            if(entry.getKey().coefficient_package <= 0){
                Package temp_package = new Package();
                for (int i = 0; i < entry.getValue(); i++) {
                    temp_package.getGoods().add(new GoodsInfo(entry.getKey()));
                }
                resPackageList_original.add(temp_package);
            }else{
                for (int i = 0; i < entry.getValue()*entry.getKey().coefficient_package; i++) {
                    Package temp_package = new Package();
                    for (int j = 0; j < 1.0/entry.getKey().coefficient_package; j++) {
                        temp_package.getGoods().add(new GoodsInfo(entry.getKey()));
                    }
                    resPackageList_original.add(temp_package);
                }
                Package temp_package = new Package();
                for (int j = 0; j < 1.0/entry.getKey().coefficient_package; j++) {
                    temp_package.getGoods().add(new GoodsInfo(entry.getKey()));
                }
                resPackageList_original.add(temp_package);
            }

        }

        for(int i = 0; i < GoodsInfoList3.size(); i++){
            Package temp_package = new Package();
            temp_package.getGoods().add(new GoodsInfo(GoodsInfoList3.get(i)));
            resPackageList_original.add(temp_package);
        }


        Alien.VCS(resPackageList_original);
        return resPackageList_original;
    }

附5、商品优先级排序

    static void goods_edge_sorting(List<GoodsInfo> goodsInfoList) {
        Collections.sort(goodsInfoList, new Comparator<GoodsInfo>() {
            @Override
            //-1优先,最长边大的放前面
            public int compare(GoodsInfo g1, GoodsInfo g2) {
                double l1 = g1.Length;
                double l2 = g2.Length;

                if(l1 > l2) {
                    return -1;
                } else{
                    return 1;
                }
            }
        });
    }

附6、自动打包逻辑

package com.jd.jingwei.algorithm.method_normal;

import com.jd.jingwei.basis.BoxInfo;
import com.jd.jingwei.basis.GoodsInfo;
import com.jd.jingwei.basis.Package;

import java.util.ArrayList;
import java.util.List;

public class StackingAuto {
    public static void auto(List<BoxInfo> boxInfoList_auto, List<BoxInfo> boxInfoList_normal, List<GoodsInfo> goodsInfoList1_auto,
                              Boolean isXiangZhuang, List<Package> resPackageList, int buffer, int buffer_auto_bag, double Threshold_box, double Threshold_bag){

        //自动包装时,不考虑buffer,在自动包装装不下时,考虑手动打包
        //目前只考虑单品的自动打包
        GoodsInfo goodsInfo = goodsInfoList1_auto.get(0);

        if(isXiangZhuang){
            int idex_auto = -1;
            int V_auto = 0;
            int idex_normal = -1;
            int V_normal = 0;

            for(int i=0; i<boxInfoList_auto.size(); i++){
                int length = Math.max(boxInfoList_auto.get(i).Length,Math.max(boxInfoList_auto.get(i).Width,boxInfoList_auto.get(i).Height));
                int height = Math.min(boxInfoList_auto.get(i).Length,Math.min(boxInfoList_auto.get(i).Width,boxInfoList_auto.get(i).Height));
                int width = boxInfoList_auto.get(i).Length+boxInfoList_auto.get(i).Width+boxInfoList_auto.get(i).Height-length-height;
                if(length>=goodsInfo.Length && width>=goodsInfo.Width && height>=goodsInfo.Height){
                    idex_auto = i;
                    V_auto = boxInfoList_auto.get(i).Volume;
                    break;
                }
            }

            for(int i=0; i<boxInfoList_normal.size(); i++){
                int length = Math.max(boxInfoList_normal.get(i).Length,Math.max(boxInfoList_normal.get(i).Width,boxInfoList_normal.get(i).Height));
                int height = Math.min(boxInfoList_normal.get(i).Length,Math.min(boxInfoList_normal.get(i).Width,boxInfoList_normal.get(i).Height));
                int width = boxInfoList_normal.get(i).Length+boxInfoList_normal.get(i).Width+boxInfoList_normal.get(i).Height-length-height;
                if(length+buffer>=goodsInfo.Length && width+buffer>=goodsInfo.Width && height+buffer>=goodsInfo.Height){
                    idex_normal = i;
                    V_normal = boxInfoList_normal.get(i).Volume;
                    break;
                }
            }
            Package temp_package = new Package();
            if(idex_auto != -1 && idex_normal != -1){
                if(goodsInfo.Volume*V_normal >= goodsInfo.Volume*V_auto-Threshold_box*V_normal*V_auto){
                    temp_package.setBox(new BoxInfo(boxInfoList_auto.get(idex_auto)));
                }else {
                    temp_package.setBox(new BoxInfo(boxInfoList_normal.get(idex_normal)));
                }
            }else if(idex_auto != -1){
                temp_package.setBox(new BoxInfo(boxInfoList_auto.get(idex_auto)));
            }else if(idex_normal != -1){
                temp_package.setBox(new BoxInfo(boxInfoList_normal.get(idex_normal)));
            }
            temp_package.getGoods().add(new GoodsInfo(goodsInfo));
            resPackageList.add(temp_package);

        }else{
            boolean code_auto = false;

            List<Double> L_V = new ArrayList<Double>();

            for(BoxInfo b:boxInfoList_auto){
                int length = Math.max(b.Length,b.Height);
                int height = Math.min(b.Length,b.Height);
                int width = b.Width;

                if(goodsInfo.Length <= width && goodsInfo.Width <= length && goodsInfo.Height <= height){
                    code_auto = true;
                    L_V.add((goodsInfo.Width+buffer_auto_bag)*goodsInfo.Height*width);
                    continue;
                }

                if(goodsInfo.Width <= width && goodsInfo.Length <= length && goodsInfo.Height <= height){
                    code_auto = true;
                    L_V.add((goodsInfo.Length+buffer_auto_bag)*goodsInfo.Height*width);
                    continue;
                }

                if(goodsInfo.Height <= width && goodsInfo.Length <= length && goodsInfo.Width <= height){
                    code_auto = true;
                    L_V.add((goodsInfo.Length+buffer_auto_bag)*goodsInfo.Width*width);
                    continue;
                }

                L_V.add(Double.MAX_VALUE);
            }

            boolean code_normal = false;
            int idex_normal = -1;
            double V_normal = Double.MAX_VALUE;
            for(int i=0; i<boxInfoList_normal.size(); i++){
                BoxInfo b = boxInfoList_normal.get(i);
                if(b.Length+b.Height-goodsInfo.Height+buffer >= goodsInfo.Length &&
                        b.Width+b.Height-goodsInfo.Height+buffer >= goodsInfo.Width){
                    code_normal = true;
                    idex_normal = i;
                    V_normal = (b.Length+b.Height-goodsInfo.Height)*(b.Width+b.Height-goodsInfo.Height)*goodsInfo.Height;
                    break;
                }
            }

            Package temp_package = new Package();
            if(code_auto) {
                int idex_auto = 0;
                for(int i=1; i<L_V.size(); i++){
                    if(L_V.get(idex_auto) > L_V.get(i)){
                        idex_auto = i;
                    }
                }
                if(code_normal){
                    if(goodsInfo.Volume*V_normal >= goodsInfo.Volume*L_V.get(idex_auto)-Threshold_bag*V_normal*L_V.get(idex_auto)){
                        temp_package.setBox(new BoxInfo(boxInfoList_auto.get(idex_auto)));
                    }else {
                        temp_package.setBox(new BoxInfo(boxInfoList_normal.get(idex_normal)));
                    }
                }else{
                    temp_package.setBox(new BoxInfo(boxInfoList_auto.get(idex_auto)));
                }
            }else if(code_normal){
                temp_package.setBox(new BoxInfo(boxInfoList_normal.get(idex_normal)));
            }
            temp_package.getGoods().add(new GoodsInfo(goodsInfo));
            resPackageList.add(temp_package);
        }
    }

}

附7、检查是否均为类缠绕膜耗材


    static Boolean ismembrane(List<BoxInfo> boxInfoList){
        Boolean flag = true;
        for(BoxInfo b: boxInfoList){
            if(b.Length > 10 || b.Width > 10 || b.Height > 10){
                flag = false;
                break;
            }
        }
        return flag;
    }

主1、商品数为1时

    public static void size_1(List<BoxInfo> boxInfoList_normal, List<GoodsInfo> goodsInfoList1,
                       Boolean isXiangZhuang, List<Package> resPackageList, int buffer){

        //由于boxInfoList_normal是按照损耗排过序的,因此遇到合适能装下的就装,然后break
        if(isXiangZhuang){
            for(BoxInfo boxInfo: boxInfoList_normal){
                if(boxInfo.Length+buffer >= goodsInfoList1.get(0).Length &&
                        boxInfo.Width+buffer >= goodsInfoList1.get(0).Width &&
                        boxInfo.Height+buffer >= goodsInfoList1.get(0).Height){
                    Package temp_package = new Package();
                    temp_package.setBox(new BoxInfo(boxInfo));
                    temp_package.getGoods().add(new GoodsInfo(goodsInfoList1.get(0)));
                    resPackageList.add(temp_package);
                    break;
                }
            }
        }else{
            for(BoxInfo boxInfo: boxInfoList_normal){
                if(boxInfo.Length+boxInfo.Height-goodsInfoList1.get(0).Height+buffer >= goodsInfoList1.get(0).Length &&
                        boxInfo.Width+boxInfo.Height-goodsInfoList1.get(0).Height+buffer >= goodsInfoList1.get(0).Width){
                    Package temp_package = new Package();
                    temp_package.setBox(new BoxInfo(boxInfo.Length+boxInfo.Height-goodsInfoList1.get(0).Height.intValue(),
                            boxInfo.Width+boxInfo.Height-goodsInfoList1.get(0).Height.intValue(),
                            goodsInfoList1.get(0).Height.intValue(),
                            boxInfo.name,
                            boxInfo.weight, 0));
                    temp_package.getGoods().add(new GoodsInfo(goodsInfoList1.get(0)));
                    resPackageList.add(temp_package);
                    break;
                }
            }
        }
    }

主2、商品数为2时

    public static void size_2(List<BoxInfo> boxInfoList_normal, List<GoodsInfo> goodsInfoList1,
                       Boolean isXiangZhuang,List<Package> resPackageList, int buffer){

        int code = 0;

        //先尝试放一个耗材里,两个商品组合成为一个更大的商品尺寸
        List<GoodsInfo> Double_Goods = new ArrayList<GoodsInfo>();

        double l1 = goodsInfoList1.get(0).Length;
        double w1 = goodsInfoList1.get(0).Width;
        double h1 = goodsInfoList1.get(0).Height;
        double l2 = goodsInfoList1.get(1).Length;
        double w2 = goodsInfoList1.get(1).Width;
        double h2 = goodsInfoList1.get(1).Height;

        Double_Goods.add(new GoodsInfo(l1+l2, Math.max(w1,w2),Math.max(h1,h2), "1", 1, 1d, 0,1));
        Double_Goods.add(new GoodsInfo(l1+w2, Math.max(w1,l2),Math.max(h1,h2), "2", 1, 1d, 0,1));
        Double_Goods.add(new GoodsInfo(l1+h2, Math.max(w1,l2),Math.max(h1,w2), "3", 1, 1d, 0,1));
        Double_Goods.add(new GoodsInfo(w1+l2, Math.max(l1,w2),Math.max(h1,h2), "4", 1, 1d, 0,1));
        Double_Goods.add(new GoodsInfo(w1+w2, Math.max(l1,l2),Math.max(h1,h2), "5", 1, 1d, 0,1));
        Double_Goods.add(new GoodsInfo(w1+h2, Math.max(l1,l2),Math.max(h1,w2), "6", 1, 1d, 0,1));
        Double_Goods.add(new GoodsInfo(h1+l2, Math.max(l1,w2),Math.max(w1,h2), "7", 1, 1d, 0,1));
        Double_Goods.add(new GoodsInfo(h1+w2, Math.max(l1,l2),Math.max(w1,h2), "8", 1, 1d, 0,1));
        Double_Goods.add(new GoodsInfo(h1+h2, Math.max(l1,l2),Math.max(w1,w2), "9", 1, 1d, 0,1));

        //保证更大尺寸的商品长大于等于宽大于等于高
        for(GoodsInfo goodsInfo: Double_Goods){
            double length = Math.max(goodsInfo.Length,Math.max(goodsInfo.Width,goodsInfo.Height));
            double height = Math.min(goodsInfo.Length,Math.min(goodsInfo.Width,goodsInfo.Height));
            double width = goodsInfo.Length+goodsInfo.Width+goodsInfo.Height-length-height;
            goodsInfo.Length = length;
            goodsInfo.Width = width;
            goodsInfo.Height = height;
        }

        //至此,耗材集合为L(L中长大于等于宽大于等于高,且最长边逐渐变长)
        // 商品可能尺寸集合为Double_Goods,尝试装载,其中一个可以装下即说明可以用单个耗材装下

        if(isXiangZhuang){
            for(BoxInfo b:boxInfoList_normal){
                for(GoodsInfo g:Double_Goods){
                    if(b.Length+buffer >= g.Length && b.Width+buffer >= g.Width && b.Height+buffer >= g.Height){
                        code = 1;
                        Package temp_package = new Package();
                        temp_package.setBox(new BoxInfo(b));
                        temp_package.getGoods().add(new GoodsInfo(goodsInfoList1.get(0)));
                        temp_package.getGoods().add(new GoodsInfo(goodsInfoList1.get(1)));
                        resPackageList.add(temp_package);
                        break;
                    }
                }
                if(code == 1){
                    break;
                }
            }
        }else{
            for(BoxInfo b:boxInfoList_normal){
                for(GoodsInfo g:Double_Goods){
                    if(b.Length+b.Height-g.Height+buffer >= g.Length && b.Width+b.Height-g.Height+buffer >= g.Width){
                        code = 1;
                        Package temp_package = new Package();
                        temp_package.setBox(new BoxInfo(b.Length+b.Height-g.Height.intValue(),
                                b.Width+b.Height-g.Height.intValue(),
                                g.Height.intValue(),
                                b.name,
                                b.weight, 0));
                        temp_package.getGoods().add(new GoodsInfo(goodsInfoList1.get(0)));
                        temp_package.getGoods().add(new GoodsInfo(goodsInfoList1.get(1)));
                        resPackageList.add(temp_package);
                        break;
                    }
                }
                if(code == 1){
                    break;
                }
            }
        }


        //一个箱子装不下,分开试装
        if(code == 0){
            List<GoodsInfo> L1 = new ArrayList<GoodsInfo>();
            List<GoodsInfo> L2 = new ArrayList<GoodsInfo>();
            L1.add(goodsInfoList1.get(0));
            L2.add(goodsInfoList1.get(1));
            size_1(boxInfoList_normal,L1,isXiangZhuang,resPackageList,buffer);
            size_1(boxInfoList_normal,L2,isXiangZhuang,resPackageList,buffer);
        }
    }

主3、商品数>=3、箱装、品类唯一

    static int one_sku_put(double CL, double CW, double CH, double l, double w, double h){

        //简单码放模式,确定码放下界
        int maxnum = ((int)(CL/l)*(int)(CW/w) + (int)((CL-(int)(CL/l)*l)/w)*(int)(CW/l))*(int)(CH/h);
        int newone = ((int)(CW/l)*(int)(CL/w) + (int)((CW-(int)(CW/l)*l)/w)*(int)(CL/l))*(int)(CH/h);
        maxnum=maxnum>=newone?maxnum:newone;

        //五块调整,当剩余面积大于一块底面积时触发
        if((int)(CL*CW/l/w)*(int)(CH/h) > maxnum & CW >= l+w) {
            int x1,x2,x3,x4,y1,y2,y3,y4;
            int up1 = (int)(CL/l), up2 = (int)(CL/w), up3 = (int)(CW/l), up4 = (int)(CW/w);
            for(x1=1; x1<=up1; x1++) {
                x2 = (int)((CL-x1*l)/w);
                for(y1=1; y1<=up4; y1++) {
                    y4 = (int)((CW-y1*w)/l);
                    for(y2=1; y2<=up3; y2++) {
                        y3 = (int)((CW-y2*l)/w);
                        for(x3=1; x3<=up1; x3++) {
                            x4 = (int)((CL-x3*l)/w);
                            if (y1*w <= y2*l && x2*w <= x3*l && y3*w <= y4*l && x4*w <= x1*l) {
                                if ((y1 + y3) * w > CW || (x2 + x4) * w > CL) {
                                    continue;
                                }
                                int n = (x1*y1+x2*y2+x3*y3+x4*y4)*(int)(CH/h);
                                maxnum=maxnum>=n?maxnum:n;
                            }
                            if (y1*w >= y2*l && x2*w >= x3*l && y3*w >= y4*l && x4*w >= x1*l){
                                if((x1+x3)*l>CL || (y2+y4)*l>CW){
                                    continue;
                                }
                                int n = (x1*y1+x2*y2+x3*y3+x4*y4)*(int)(CH/h);
                                maxnum=maxnum>=n?maxnum:n;
                            }
                        }
                    }
                }

            }
        }
        return maxnum;
    }

    public static void one_sku_size_more(List<BoxInfo> boxInfoList_normal, List<GoodsInfo> goodsInfoList1,
                                       List<Package> resPackageList, int buffer){

        double l = goodsInfoList1.get(0).Length;
        double w = goodsInfoList1.get(0).Width;
        double h = goodsInfoList1.get(0).Height;
        int nums_goods = goodsInfoList1.size();

        List<Pair<Integer,Integer>> nums_can_put = new ArrayList<Pair<Integer, Integer>>();

        int max_loc = 0;
        for (int i = 0; i < boxInfoList_normal.size(); i++) {
            double CL = boxInfoList_normal.get(i).Length + buffer;
            double CW = boxInfoList_normal.get(i).Width + buffer;
            double CH = boxInfoList_normal.get(i).Height + buffer;
            //筛选,只把那些利用率比较高的存下来
            int num1 = one_sku_put(CL, CW, CH, l, w, h);
            int num2 = one_sku_put(CL, CH, CW, l, w, h);
            int num3 = one_sku_put(CW, CH, CL, l, w, h);
            int num4 = one_sku_put(CL, CW, CH, l, h, w);
            int num5 = one_sku_put(CL, CH, CW, l, h, w);
            int num6 = one_sku_put(CW, CH, CL, l, h, w);
            int num7 = one_sku_put(CL, CW, CH, w, h, l);
            int num8 = one_sku_put(CL, CH, CW, w, h, l);
            int num9 = one_sku_put(CW, CH, CL, w, h, l);

            int num = num1;
            num = num>=num2?num:num2;
            num = num>=num3?num:num3;
            num = num>=num4?num:num4;
            num = num>=num5?num:num5;
            num = num>=num6?num:num6;
            num = num>=num7?num:num7;
            num = num>=num8?num:num8;
            num = num>=num9?num:num9;

            if(num > max_loc){
                max_loc = num;
                nums_can_put.add(new Pair<Integer, Integer>(i,num));
            }
        }

        if(nums_can_put.size() == 0){
            return;
        }

        if(nums_can_put.get(nums_can_put.size()-1).getValue() == 0){
            return;
        }

        int goods_left = nums_goods;

        while(goods_left >= nums_can_put.get(nums_can_put.size()-1).getValue()){
            Package temp_package = new Package();
            temp_package.setBox(new BoxInfo(boxInfoList_normal.get(nums_can_put.get(nums_can_put.size()-1).getKey())));
            for (int i = 0; i < nums_can_put.get(nums_can_put.size()-1).getValue(); i++) {
                temp_package.getGoods().add(new GoodsInfo(goodsInfoList1.get(0)));
            }
            resPackageList.add(temp_package);
            goods_left -= nums_can_put.get(nums_can_put.size()-1).getValue();
        }

        if(goods_left == 0){
            return;
        }

        int idex = nums_can_put.size()-1;

        while(idex > 0){
            if(nums_can_put.get(idex-1).getValue() >= goods_left){
                idex -= 1;
            }else{
                break;
            }
        }

        Package temp_package = new Package();
        temp_package.setBox(new BoxInfo(boxInfoList_normal.get(nums_can_put.get(idex).getKey())));
        for (int i = 0; i < goods_left; i++) {
            temp_package.getGoods().add(new GoodsInfo(goodsInfoList1.get(0)));
        }
        resPackageList.add(temp_package);

    }

主4、袋子集扩充为箱子集

    static List<BoxInfo> createBagList(List<BoxInfo> boxInfoList , int num_sup) {

        List<BoxInfo> bagList_normal = new ArrayList<BoxInfo>();

        for (BoxInfo boxInfo : boxInfoList) {
            //袋子交换宽和高,宽最短,高次短
            int length = boxInfo.Length;
            int width = boxInfo.Height;
            int height = boxInfo.Width;

            int step = (length - width) / (2 * num_sup);

            if (step % 10 > 0) {
                step = step + 10 - step % 10;
            }

            if (step <= 0) {
                bagList_normal.add(new BoxInfo(length, width, height, boxInfo.name, boxInfo.weight, 0));
            } else {
                while (length >= width && height > 0) {
                    bagList_normal.add(new BoxInfo(length, width, height, boxInfo.name, boxInfo.weight, 0));
                    length -= step;
                    width += step;
                    height -= step;
                }
            }
        }

        for(BoxInfo boxInfo:bagList_normal){
            int length = Math.max(boxInfo.Length,Math.max(boxInfo.Width,boxInfo.Height));
            int height = Math.min(boxInfo.Length,Math.min(boxInfo.Width,boxInfo.Height));
            int width = boxInfo.Length+boxInfo.Width+boxInfo.Height-length-height;
            boxInfo.Length = length;
            boxInfo.Width = width;
            boxInfo.Height = height;
        }

        return bagList_normal;
    }

主5、商品数>=3正常启发式逻辑

package com.jd.jingwei.algorithm.method_normal;

import com.jd.jingwei.basis.BoxInfo;
import com.jd.jingwei.basis.GoodsInfo;
import com.jd.jingwei.basis.Package;
import com.jd.jingwei.tool.*;

import java.util.ArrayList;
import java.util.List;

public class StackingHeuristic {

    static Boolean feasible(BoxInfo b, List<GoodsInfo> realGoodsInfoList){
        Boolean code = true;

        for (GoodsInfo g:realGoodsInfoList){
            if(b.Length<g.Length || b.Width<g.Width || b.Height<g.Height){
                code = false;
            }
        }

        return code;
    }

    //对于一类耗材,看最多需要几个耗材装下待装货物,属于装箱问题,这里采用简单版装载
    static Pair<BoxInfo,Integer> simplePacking(BoxInfo b, List<GoodsInfo> realGoodsInfoList){

        int CL = b.Length;
        int CW = b.Width;
        int CH = b.Height;

        //首先判定每个商品是否都能装下,装不下则直接略过
        if(!feasible(b,realGoodsInfoList)){
            return new Pair<BoxInfo,Integer>(b,-1);
        }

        //将商品按照高度CH约束摞成条状,转为二维问题,存在rectangle中
        List<List<Double>> rectangle = new ArrayList<List<Double>>();

        double length_used = 0;
        double width_used = 0;
        double height_used = 0;

        //Goods_used_state表示每个Good的使用状态
        List<Integer> Goods_used_state = new ArrayList<Integer>();
        for(GoodsInfo g:realGoodsInfoList){
            Goods_used_state.add(1);
        }

        while(num_exist(Goods_used_state)>0){

            length_used = 0;
            width_used = 0;
            height_used = 0;

            for(int i=0; i<Goods_used_state.size(); i++){
                if(Goods_used_state.get(i) == 1 && height_used+realGoodsInfoList.get(i).Height <= CH){
                    height_used += realGoodsInfoList.get(i).Height;
                    length_used = Math.max(length_used, realGoodsInfoList.get(i).Length);
                    width_used = Math.max(width_used, realGoodsInfoList.get(i).Width);
                    Goods_used_state.set(i,0);
                }
            }

            List<Double> temp_L = new ArrayList<Double>();
            temp_L.add(length_used);
            temp_L.add(width_used);
            rectangle.add(temp_L);

        }

        //摞转成条,用CW去卡,存在length_set中
        List<Double> length_set = new ArrayList<Double>();

        List<Integer> rec_used_state = new ArrayList<Integer>();
        for(int i=0; i<rectangle.size(); i++){
            rec_used_state.add(1);
        }

        double width_used_1 = 0;
        double l_bar = 0;

        while(num_exist(rec_used_state)>0){

            width_used_1 = 0;
            l_bar = 0;

            for(int i=0; i<rec_used_state.size(); i++){
                if(rec_used_state.get(i) == 1 && width_used_1+rectangle.get(i).get(1) <= CW){
                    width_used_1 += rectangle.get(i).get(1);
                    l_bar = Math.max(l_bar,rectangle.get(i).get(0));
                    rec_used_state.set(i,0);
                }
            }

            length_set.add(l_bar);

        }

        //计算需要多少箱子
        List<Double> box_status = new ArrayList<Double>();
        box_status.add(0d);

        for(Double l:length_set){
            int code = 0;
            for(int i = 0;i<box_status.size();i++){
                if(l+box_status.get(i) <= CL){
                    box_status.set(i,box_status.get(i)+l);
                    code = 1;
                    break;
                }
            }
            if(code == 0){
                box_status.add(l);
            }
        }

        return new Pair<BoxInfo,Integer>(b,box_status.size());

    }

    //判断是否存在没有形成条的箱子
    static Integer num_exist(List<Integer>Goods_used_state){
        Integer sum_state = 0;
        for(Integer i:Goods_used_state){
            sum_state += i;
        }
        return sum_state;
    }

    static void pushgoods(List<GoodsInfo> L, List<List<GoodsInfo>> res_LL, int idex){
        for(GoodsInfo g:L){
            res_LL.get(idex).add(new GoodsInfo(g));
        }
    }

    static List<GoodsInfo> breaking(List<List<GoodsInfo>> LL){

        List<GoodsInfo> L = new ArrayList<GoodsInfo>();

        for(int i=0; i<LL.size();i++){
            for(int j=0;j<LL.get(i).size();j++){
                L.add(LL.get(i).get(j));
            }
        }

        return L;

    }


    public static void Packing(BoxInfo b, List<GoodsInfo> realGoodsInfoList, List<Package> resPackageList, List<BoxInfo> L_box, Boolean isXiangZhuang, int buffer){

        int CL = b.Length;
        int CW = b.Width;
        int CH = b.Height;

        //将商品按照高度CH约束摞成条状,转为二维问题,存在rectangle中,LL与其同步
        List<List<Double>> rectangle = new ArrayList<List<Double>>();
        List<List<GoodsInfo>> LL = new ArrayList<List<GoodsInfo>>();

        double length_used = 0;
        double width_used = 0;
        double height_used = 0;

        List<GoodsInfo> L = new ArrayList<GoodsInfo>();

        //Goods_used_state表示每个Good的使用状态
        List<Integer> Goods_used_state = new ArrayList<Integer>();
        for(GoodsInfo g:realGoodsInfoList){
            Goods_used_state.add(1);
        }

        while(num_exist(Goods_used_state)>0){

            L = new ArrayList<GoodsInfo>();
            length_used = 0;
            width_used = 0;
            height_used = 0;

            for(int i=0; i<Goods_used_state.size(); i++){
                if(Goods_used_state.get(i) == 1 && height_used+realGoodsInfoList.get(i).Height <= CH){
                    height_used += realGoodsInfoList.get(i).Height;
                    length_used = Math.max(length_used, realGoodsInfoList.get(i).Length);
                    width_used = Math.max(width_used, realGoodsInfoList.get(i).Width);
                    L.add(new GoodsInfo(realGoodsInfoList.get(i)));
                    Goods_used_state.set(i,0);
                }
            }

            List<Double> temp_L = new ArrayList<Double>();
            temp_L.add(length_used);
            temp_L.add(width_used);
            rectangle.add(temp_L);
            LL.add(L);

        }

        //摞转成条,用CW去卡,存在length_set中,同步在LLL中
        List<List<List<GoodsInfo>>> LLL = new ArrayList<List<List<GoodsInfo>>>();
        List<List<GoodsInfo>> temp_LL = new ArrayList<List<GoodsInfo>>();

        List<Double> length_set = new ArrayList<Double>();

        List<Integer> rec_used_state = new ArrayList<Integer>();
        for(int i=0; i<rectangle.size(); i++){
            rec_used_state.add(1);
        }

        double width_used_1 = 0;
        double l_bar = 0;

        while(num_exist(rec_used_state)>0){

            temp_LL = new ArrayList<List<GoodsInfo>>();
            width_used_1 = 0;
            l_bar = 0;

            for(int i=0; i<rec_used_state.size(); i++){
                if(rec_used_state.get(i) == 1 && width_used_1+rectangle.get(i).get(1) <= CW){
                    width_used_1 += rectangle.get(i).get(1);
                    l_bar = Math.max(l_bar,rectangle.get(i).get(0));
                    temp_LL.add(Copy.L_good_copy(LL.get(i)));
                    rec_used_state.set(i,0);
                }
            }

            length_set.add(l_bar);
            LLL.add(temp_LL);
        }

        //计算需要多少箱子
        List<Double> box_status = new ArrayList<Double>();
        List<List<GoodsInfo>> res_LL = new ArrayList<List<GoodsInfo>>();

        box_status.add(0d);
        res_LL.add(new ArrayList<GoodsInfo>());

        for(int i=0; i<length_set.size(); i++){
            int code = 0;
            for(int j = 0;j<box_status.size();j++){
                if(length_set.get(i)+box_status.get(j) <= CL){
                    box_status.set(j,box_status.get(j)+length_set.get(i));
                    pushgoods(breaking(LLL.get(i)),res_LL,j);
                    code = 1;
                    break;
                }
            }
            if(code == 0){
                box_status.add(length_set.get(i));
                res_LL.add(Copy.L_good_copy(breaking(LLL.get(i))));
            }
        }

        //包裹添加,除了最后一个其他都正常添加,最后一个很可能发生填充率较低,故根据其内的商品个数判断是否重新选用耗材
        for(int i=0; i<res_LL.size()-1;i++){

            Package temp_package = new Package();
            temp_package.setBox(new BoxInfo(b));

            for(int j=0;j<res_LL.get(i).size();j++) {
                temp_package.getGoods().add(new GoodsInfo(res_LL.get(i).get(j)));
            }

            resPackageList.add(temp_package);
        }

        //当最后一个商品货物1个或2个时,直接调用现成方法,否则直接装载
        List<GoodsInfo> end_goods = Copy.L_good_copy(res_LL.get(res_LL.size()-1));
        if(end_goods.size() == 1){
            StackingSimple.size_1(L_box, end_goods,isXiangZhuang,resPackageList,buffer);
        }else if(end_goods.size() == 2){
            StackingSimple.size_2(L_box, end_goods,isXiangZhuang,resPackageList, buffer);
        }else{
            Package temp_package = new Package();
            temp_package.setBox(new BoxInfo(b));
            for(int j=0;j<end_goods.size();j++) {
                temp_package.getGoods().add(new GoodsInfo(end_goods.get(j)));
            }
            resPackageList.add(temp_package);
        }

    }

    public static void size_more(List<BoxInfo> boxInfoList, List<BoxInfo> bagList, List<GoodsInfo> realGoodsInfoList,
                          Boolean isXiangZhuang, List<Package> resPackageList, int buffer){

        List<BoxInfo> L;

        if(isXiangZhuang){
            L = boxInfoList;
        } else {
            L = bagList;
        }

        //由于3个及3个以上解空间过大,在此采用启发式方法,先对应每组货物,用一类耗材去装,看最多需要几个耗材

        List<Pair<BoxInfo,Integer>> boxesNeed_per_box = new ArrayList<Pair<BoxInfo, Integer>>();

        for(BoxInfo b:L){

            Pair<BoxInfo,Integer> temp_res = simplePacking(b,realGoodsInfoList);
            if(temp_res.getValue() == -1){
                continue;
            }
            boxesNeed_per_box.add(temp_res);
        }

        //当没有一个耗材能够满足所有商品时,分成单包裹推荐
        if(boxesNeed_per_box.size() == 0){
            for(GoodsInfo g: realGoodsInfoList) {
                List<GoodsInfo> L_g = new ArrayList<GoodsInfo>();
                L_g.add(g);
                StackingSimple.size_1(boxInfoList, L_g, isXiangZhuang, resPackageList, buffer);
            }
            return;
        }

        //从boxesNeed_per_box中挑选最好的耗材,标准是,先选耗材消耗少的,同等耗材数时耗材体积小的优先

        int num_box_used = boxesNeed_per_box.get(0).getValue();

        for(Pair<BoxInfo,Integer> p:boxesNeed_per_box){
            num_box_used = Math.min(num_box_used,p.getValue());
        }

        int V = Integer.MAX_VALUE;
        BoxInfo b = new BoxInfo(boxesNeed_per_box.get(0).getKey());

        for(Pair<BoxInfo,Integer> p:boxesNeed_per_box){
            if(p.getValue() == num_box_used && V > p.getKey().Volume){
                V = p.getKey().Volume;
                b = new BoxInfo(p.getKey());
            }
        }

        //耗材选定为b,商品集合为realGoodsInfoList,开始装载
        Packing(b, realGoodsInfoList, resPackageList,L,isXiangZhuang,buffer);

    }


}

主6、包裹汇总

    static void packageSummary(List<Package> resPackageList){

        for(Package mPackage : resPackageList) {
            if(mPackage.getBox() != null) {
                mPackage.setTotalWeight(mPackage.getTotalWeight() + mPackage.getBox().weight);
                mPackage.setBoxName(mPackage.getBox().name);
            }else{
                if(mPackage.getGoods().size() > 0){
                    if(mPackage.getGoods().get(0).flag == 3){
                        mPackage.setBoxName("original");
                    }else{
                        mPackage.setBoxName("alien");
                    }
                }else{
                    mPackage.setBoxName(" ");
                }
            }
            Set<String> skuSet = new HashSet<String>();
            Map<String, Integer> skuCountMap = new HashMap<String, Integer>();
            for(GoodsInfo goodsInfo : mPackage.getGoods()) {
                mPackage.setTotalWeight(mPackage.getTotalWeight() + goodsInfo.goodsWeight);
                skuSet.add(goodsInfo.sku);
                if(!skuCountMap.containsKey(goodsInfo.sku)) {
                    skuCountMap.put(goodsInfo.sku, 0);
                }
                skuCountMap.put(goodsInfo.sku, skuCountMap.get(goodsInfo.sku) + 1);
            }
            mPackage.setSkuList(new ArrayList<String>(skuSet));
            mPackage.setSkuCountMap(skuCountMap);
            mPackage.setTotalGoodsCount(mPackage.getGoods().size());
        }
    }

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值