有名字的风
2019-05-05 10:43
采纳率: 100%
浏览 1.5k
已采纳

三维装箱(Java)求优化或给出更好的代码方案

代码效率太低,货品一多会导致内存溢出.求优化或给出更好的解决方案

package com.example.demo.box;


import java.util.*;

public class GoodsInBox {
    /*箱子的型号,盛放空间*/
    private Map<Integer,Map<String,Object>> boxTypeArr;
    /*订单中的商品*/
    private Map<Integer,Map<String,Integer>> orderItemArr;
    /*计算结果*/
    private Map<String /*箱子型号*/,Integer/*需要几个*/> result=new HashMap<String,Integer>();
    /*计算过程数据,有效的空间列表*/
    private List<String> inboxinfo=new ArrayList<String>();

    /**
     * 根据箱型以及订单中的商品,返回每个箱型需要箱子多少只。如果没有任何的箱子能装下某一款超大商品的时候,抛出异常
     *
     * @param linkedHashMap
     * @param orderItemArr
     * @return
     */
    public GoodsInBox(LinkedHashMap<Integer, Map<String, Object>> linkedHashMap, Map<Integer, Map<String, Integer>> orderItemArr){
        this.boxTypeArr = linkedHashMap;
        this.orderItemArr=orderItemArr;
        //开始执行
        run();
    }


    /**
     * boxType.get(boxkey)  value{boxcode=1, l=100, w=100, h=120}
     * boxType.get(boxkey) {boxcode=2, l=200, w=150, h=180}
     * boxType.get(boxkey) {boxcode=3, l=500, w=600, h=700}
     */
    //执行装箱
    private void run(){
        Integer[] boxkeys=boxTypeArr.keySet().toArray(new Integer[]{});
        aBoxType: for (Integer boxkey : boxkeys) {
            tryInSpance(boxTypeArr.get(boxkey), orderItemArr);
        }
    }

    /**
     * 每次测试1块空间,和全部商品,将商品一次向空间转移,放进去后产生新的3块空间,同时商品的数量再减少,直到商品全部转移;
     * @param boxMap
     * @param products
     */
    private void tryInSpance(Map<String/* 长l宽w高h */, Object/* 厘米 */> boxMap/* 某1个盒子或者是1个剩餘空間 */,
                             Map<Integer, Map<String, Integer>> products/* 多件商品,装进去一件,删除一件,直到删没了为止 */){
        if (null == boxMap || null == products) {
            return;
        }
        java.util.Iterator<Integer> gks = products.keySet().iterator();    //对存储商品的Map进行遍历
        while (gks.hasNext()) {
            Integer oid = gks.next();                      //oid就是products的Key
            Map<String, Integer> g = products.get(oid);    //g是具体的商品属性
            // 商品数量
            Integer num = g.get("n");     //获取某种商品的数量
            if (0 == num) {
                return;
            }
            // 多少件商品就循环多少次,每次处理一件;
            for (int i = num; i > 0; i--) {
                String boxcode = boxMap.get("boxcode").toString().concat(":").concat(oid.toString());   //箱的Kye:商品的Key    1:1
                Integer bl = Integer.valueOf(boxMap.get("l").toString());       //箱的长
                Integer bw = Integer.valueOf(boxMap.get("w").toString());       //箱的宽
                Integer bh = Integer.valueOf(boxMap.get("h").toString());       //箱的高
                Integer gl = g.get("l");                                        //商品的长
                Integer gw = g.get("w");                                        //商品的宽
                Integer gh = g.get("h");                                        //商品的高
                // 正面放置商品
                if ((bl - gl) >= 0 && (bw - gw) >= 0 && (bh - gh) >= 0) {
                    // 可以放入的情况下先减少商品的数量;
                    g.put("n", i - 1);
                    // 加入统计
                    inboxinfo.add(boxcode);
                    // 正放的3块剩余空间
                    Map<String, Object> leftover;
                    // 第一块空间
                    leftover = new HashMap<String, Object>();
                    leftover.put("boxcode", boxcode.concat("-1:").concat(oid.toString()));
                    leftover.put("l", gl);
                    leftover.put("w", gw);
                    leftover.put("h", bh - gh);
                    tryInSpance(leftover, products);
                    // 第二块空间
                    leftover = new HashMap<String, Object>();
                    leftover.put("boxcode", boxcode.concat("-2:").concat(oid.toString()));
                    leftover.put("l", gl);
                    leftover.put("w", bw - gw);
                    leftover.put("h", bh);
                    tryInSpance(leftover, products);
                    // 第三块空间
                    leftover = new HashMap<String, Object>();
                    leftover.put("boxcode", boxcode.concat("-3:").concat(oid.toString()));
                    leftover.put("l", bl - gl);
                    leftover.put("w", bw);
                    leftover.put("h", bh);
                    tryInSpance(leftover, products);

                    // 侧面放置商品
                } else if ((bl - gw) >= 0 && (bw - gl) >= 0 && (bh - gh) >= 0) {
                    // 可以放入的情况下先减少商品的数量;
                    g.put("n", i - 1);
                    // 加入统计
                    inboxinfo.add(boxcode);
                    // 侧放的3块剩余空间
                    Map<String, Object> leftover;
                    // 第一块空间
                    leftover = new HashMap<String, Object>();
                    leftover.put("boxcode", boxcode.concat("-1:").concat(oid.toString()));
                    leftover.put("l", gl);
                    leftover.put("w", gw);
                    leftover.put("h", bh - gh);
                    tryInSpance(leftover, products);
                    // 第二块空间
                    leftover = new HashMap<String, Object>();
                    leftover.put("boxcode", boxcode.concat("-2:").concat(oid.toString()));
                    leftover.put("l", bw - gl);
                    leftover.put("w", gw);
                    leftover.put("h", bh);
                    tryInSpance(leftover, products);

                    // 第三块空间
                    leftover = new HashMap<String, Object>();
                    leftover.put("boxcode", boxcode.concat("-3:").concat(oid.toString()));
                    leftover.put("l", bl - gw);
                    leftover.put("w", bw);
                    leftover.put("h", bh);
                    tryInSpance(leftover, products);

                    // 卧倒放置商品
                } else if (g.get("t") == 1 && (bl - gh) >= 0 && (bw - gw) >= 0 && (bw - gl) >= 0) {
                    // 可以放入的情况下先减少商品的数量;
                    g.put("n", i - 1);
                    // 加入统计
                    inboxinfo.add(boxcode);
                    // 侧放的3块剩余空间
                    Map<String, Object> leftover;
                    // 第一块空间
                    leftover = new HashMap<String, Object>();
                    leftover.put("boxcode", boxcode.concat("-1:").concat(oid.toString()));
                    leftover.put("l", gh);
                    leftover.put("w", gw);
                    leftover.put("h", bh - gh);
                    tryInSpance(leftover, products);

                    // 第二块空间
                    leftover = new HashMap<String, Object>();
                    leftover.put("boxcode", boxcode.concat("-2:").concat(oid.toString()));
                    leftover.put("l", bw - gw);
                    leftover.put("w", gh);
                    leftover.put("h", bh);
                    tryInSpance(leftover, products);

                    // 第三块空间
                    leftover = new HashMap<String, Object>();
                    leftover.put("boxcode", boxcode.concat("-3:").concat(oid.toString()));
                    leftover.put("l", bl - gh);
                    leftover.put("w", bw);
                    leftover.put("h", bh);
                    tryInSpance(leftover, products);

                    // 侧卧放置商品
                } else if (g.get("t") == 1 && (bl - gw) >= 0 && (bh - gl) >= 0 && (bw - gh) >= 0) {
                    // 可以放入的情况下先减少商品的数量;
                    g.put("n", i - 1);
                    // 加入统计
                    inboxinfo.add(boxcode);
                    // 侧放的3块剩余空间
                    Map<String, Object> leftover;
                    // 第一块空间
                    leftover = new HashMap<String, Object>();
                    leftover.put("boxcode", boxcode.concat("-1:").concat(oid.toString()));
                    leftover.put("l", gw);
                    leftover.put("w", gh);
                    leftover.put("h", bh - gl);
                    tryInSpance(leftover, products);
                    // 第二块空间
                    leftover = new HashMap<String, Object>();
                    leftover.put("boxcode", boxcode.concat("-2:").concat(oid.toString()));
                    leftover.put("l", bw - gh);
                    leftover.put("w", gw);
                    leftover.put("h", bh);
                    tryInSpance(leftover, products);
                    // 第三块空间
                    leftover = new HashMap<String, Object>();
                    leftover.put("boxcode", boxcode.concat("-3:").concat(oid.toString()));
                    leftover.put("l", bl - gw);
                    leftover.put("w", bw);
                    leftover.put("h", bh);
                    tryInSpance(leftover, products);

                }
            }
        }
    }

    /**
     * 返回计算后得到的结果
     * @return
     */
    public Map<String/* 箱子的型号 */, Integer/* 需要几个 */> getResult(){
        result.clear();
        // 这里开始数数了!
        // 所有装入盒子的商品都放到列表中了,
        // length为特定长度(3)的为商品第一次装入箱子,其它过长(>3)的都是小件商品塞到之前的箱子里的。
        // 以上运行的结果应该是:最少需要1号箱两个,3号箱1个,
        for (String code : inboxinfo) {
            if (code.length() == 3) {
                String boxno = String.valueOf(code.split(":")[0]);
                Integer num = result.get(boxno);
                if (null == num)
                    num = 0;
                num = num + 1;
                result.put(boxno + "", num);
            }
        }
        return this.result;
    }

    public static void main(String[] arproducts) {
        GoodsInBox gb = new GoodsInBox(/* 箱子的规格 */new LinkedHashMap<Integer, Map<String, Object>>() {
            {
                // 假设有大中小三种型号的箱子,如下描述:
                /*-
                 *  要求数据从数据库中取出来的时候是按照 箱子型号大小系数 (l长+w款+h高) 从小到大的顺序排好序的。這樣裝箱后可以得到近似合理的解
                 */
                // 1,小箱
                this.put(1, new LinkedHashMap<String, Object>() {
                    {
                        // 小箱 长 100厘米,宽100厘米,高120厘米;
                        this.put("boxcode", 1);
                        this.put("l", 100);
                        this.put("w", 100);
                        this.put("h", 120);
                    }
                });
                // 2,中箱
                this.put(2, new LinkedHashMap<String, Object>() {
                    {
                        // 中箱 长200厘米,宽150厘米,高180厘米
                        this.put("boxcode", 2);
                        this.put("l", 200);
                        this.put("w", 150);
                        this.put("h", 180);
                    }
                });
                // 3,大箱
                this.put(3, new LinkedHashMap<String, Object>() {
                    {
                        // 大箱长500厘米宽600厘米高700厘米
                        this.put("boxcode", 3);
                        this.put("l", 500);
                        this.put("w", 600);
                        this.put("h", 700);
                    }
                });

            }
        }, /* 订单 */ new LinkedHashMap<Integer, Map<String, Integer>>() {
            {
                /*-
                 *  要求数据从数据库中取出来的时候是按照 商品大小系数 (l长+w款+h高) 从大到小的顺序排好序的。這樣裝箱后可以得到近似合理的解
                 */
                // 1,卧室用的小冰箱1个
                this.put(1, new LinkedHashMap<String, Integer>() {
                    {
                        // 长 400厘米,宽500厘米,高600厘米;
                        this.put("l", 400);
                        this.put("w", 500);
                        this.put("h", 600);
                        this.put("n", 10);
                        this.put("t", 0);// 是否可以躺着放,0,否;1,是,这个不能躺着放,而且所有商品均不能倒置,而且倒置和正着放置所占用空间一样。
                    }
                });
                // 1,电脑主机箱2台
                this.put(2, new LinkedHashMap<String, Integer>() {
                    {
                        // 长 57厘米,宽21厘米,高52厘米;
                        this.put("l", 1);
                        this.put("w", 1);
                        this.put("h", 1);
                        this.put("n", 5);
                        this.put("t", 1);// 是否可以躺着放,0,否;1,是
                    }
                });
                // 2,苹果笔记本电脑10台
                this.put(3, new LinkedHashMap<String, Integer>() {
                    {
                        // 长 33厘米,宽24厘米,高6厘米;
                        this.put("l", 1);
                        this.put("w", 1);
                        this.put("h", 1);
                        this.put("n", 5);
                        this.put("t", 1);// 是否可以躺着放,0,否;1,是
                    }
                });

            }
        });

        // 1号箱子 2只,分别装笔记本和小键盘; 3号箱子:1只用来装冰箱
        System.out.println(gb.getResult().toString());
    }
}

2条回答 默认 最新

相关推荐 更多相似问题