二維裝箱裝怎麼能裝最多

問題描述:
在這裏插入圖片描述
上面的描述是一個三維的裝箱問題,但是題目說大箱子的長度和小箱子的長度相同,所以可以轉換爲一個二維空間上的裝箱問題,只考慮寬和高。
思考:

  1. 怎麼裝才能保證裝的最多?從最小的開始裝,裝到裝不下了就是最多的情況。(揹包問題)
  2. 但是小方塊不規則,會有很多空隙存在,那麼在計算剩餘空間的時候,用剩餘總空間減去當前小方塊的空間這樣的做法是有問題的,因爲小方塊不可能像理想的那樣緊湊的在一起。

解決方法:

  1. 要裝下最多,首先能確定的是空間小的優先是能保證裝的最多。
  2. 要能充分的利用空間,但是又不能以理想的方式直接用總的減去當前的。其實用二分的方法可以充分的利用空間,就是將第一個矩形放入盒子後,將盒子分爲右、下兩個盒子,然後繼續在右和下兩個盒子中裝第二個矩形,然後裝下了又劃分。(參考
  3. 上面解決了裝最多,和充分利用空間的問題,但是充分利用空間的方法是從大開始裝,因爲這樣劃分的空間纔有可能裝下後面比它小的矩形。要是從最小的開始裝,那麼劃分後剩餘的空間是裝不下還比它大的矩形的。所以1和2兩個思路分別解決了問題,但是矛盾了。
  4. 那麼又要優先裝小的,又要從大的開始裝。怎麼解決? 我的思路是:從大的開始裝,裝到裝不下了,看是否有剩餘的小矩形,如果有!那麼把最大的一個矩形剔除,從第二大的開始裝,重複上面步驟,知道最小的一個裝到盒子裏面,那麼這樣的情況一定是最多而且最緊湊的。

代碼的實現:

節點類 Node.java

public class Node {
    public Integer x;
    public Integer y;
    public Integer w;
    public Integer h;
    public boolean isUsed;
    public Node right;
    public Node down;
    public Rectangle rec;


    public Node() {
    }

    public Node(Integer x, Integer y, Integer w, Integer h) {
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
    }

    public Integer getX() {
        return x;
    }

    public void setX(Integer x) {
        this.x = x;
    }

    public Integer getY() {
        return y;
    }

    public void setY(Integer y) {
        this.y = y;
    }

    public Integer getW() {
        return w;
    }

    public void setW(Integer w) {
        this.w = w;
    }

    public Integer getH() {
        return h;
    }

    public void setH(Integer h) {
        this.h = h;
    }

    public boolean isUsed() {
        return isUsed;
    }

    public void setUsed(boolean used) {
        isUsed = used;
    }

    public Node getRight() {
        return right;
    }

    public void setRight(Node right) {
        this.right = right;
    }

    public Node getDown() {
        return down;
    }

    public void setDown(Node down) {
        this.down = down;
    }

    public Rectangle getRec() {
        return rec;
    }

    public void setRec(Rectangle rec) {
        this.rec = rec;
    }
}

核心類 Core.java

public class Core {

    private Node root;
    private Integer templateWidth;
    private Integer templateHeight;
    public List<Rectangle> datas;

    public Core(List<Rectangle> datas,Integer templateWidth, Integer templateHeight) {
        this.templateWidth = templateWidth;
        this.templateHeight = templateHeight;
        this.datas = datas;
    }

    public Node paking(){
        this.root = new Node(0,0,templateWidth,templateHeight);
        for (Rectangle item : datas){
            if(!item.isUsed){//沒有裝入
                Node currentNode = this.findNode(root,item);
                if (currentNode != null){//裝下去了
                    this.splitPlate(currentNode,item);//劃分
                    item.isUsed = true;
                }
                else {
                    return  this.root;
                }
            }
        }
        return this.root;
    }

    private Node findNode(Node root,Rectangle rectangle){
        if (root.isUsed){//已經劃分成兩塊(右  下)
            Node node = findNode(root.right,rectangle);
            if (node == null){//左邊裝不下
                node = findNode(root.down,rectangle);//從右邊裝
            }
            return node;
        } else if (rectangle.w <= root.w && rectangle.h <= root.h){//區間能裝下小矩形
            root.setRec(rectangle);
            return root;
        }else {//裝不下了
            return null;
        }
    }

    private Node splitPlate(Node node,Rectangle rectangle){//劃分容器
        node.isUsed = true;//s說明容器已經劃分了
        node.down = new Node(node.x,rectangle.h,node.w,node.h-rectangle.h);//x,y,w,h
        node.right = new Node(node.y,rectangle.w,node.w-rectangle.w,rectangle.h);
        return node;
    }
}

歡迎評論留言交流
留個羣,嘻嘻嘻
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章