Loading problem | branch and bound method (upper bound)

Loading problems: there are n 2 containers to be loaded on the carrier by weight of c1 and c2 are the ship, wherein the weight of the container i is Wi , and Σwi <= c1 + c2.

Ask if there is a reasonable loading plan to load these n containers on these 2 ships. If so, find a loading plan.

Problem analysis: In fact, it can be understood as whether it is possible to load all the goods on the first ship and then the second ship and give a solution.

The main thing to consider is how to install the first ship? After this problem is solved, the rest can be put into the second ship.


       I discussed loading issues before, Portal: Loading issues | Backtracking: 01 selection (maximum pruning) . It discusses the comparison between the loading problem and the optimal loading problem. Greedy algorithm is not allowed in this question! I won't repeat it here. In fact, it can be seen from the above that backtracking is to perform dfs on all schemes, and pruning optimization in the middle . The branch and bound rule here is to perform bfs on all solutions, and always search from the best point each time.


1. The branch and bound algorithm of the selection tree

       After understanding the essence of enumeration (selection tree) in the backtracking algorithm, it is easy to use branch boundaries. The details will not be explained here, just change the dfs of the backtracking to bfs . For detailed discussion, see Loading Issues | Backtracking: 01 selection (maximum pruning) .

      The following is the model of the decision tree, in which the node to be discussed should be stored in a priority queue with a key bit . The node with the largest key is removed each time to continue the discussion.


    The most important thing here is to pay attention to the understanding of each node :

  • The node should be the result of a decision plan running to a certain location
  • The nodes should have: cur_w (the current weight of the ship), r (the total weight of the remaining unselected items), the keyword key (cur_w + r), and step (the next item should be selected to obtain the item number)
  • When the node is taken out, the discussion should continue under the data state saved by the node: whether to put the step item, there are two choices. Continue to add appropriate decision child nodes to the priority queue     

note:

  1. Each weight of our items is stored in the array w, starting from 0. Therefore, when step = n in the node, it means that the node is a leaf node, and the decision has been completed!
  2. The keyword key is actually the upper bound of the final answer of the decision line that this node exists!

        This branch and bound method has been optimized and pruned, which has been added: constraint conditions, bound conditions. So some of the decision points in the figure above are omitted! 


2. Code implementation

#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;

typedef struct node {
    int key;     //key = cur_w + r,关键字:上界
    int cur_w;   //当前船上的重量
    int r;       //未选择货物的剩余总重
    int step = 0;  //当前搜索的层数(在讨论哪个物品)

    /* 构造函数 */
    node(int k, int cw, int r, int s) {
        key = k;
        cur_w = cw;
        this->r = r;
        step = s;
    }

    /* 重载 struct node 的比较运算符
     *  方便后面建立优先队列的大小定位 */
    friend bool operator<(struct node x, struct node y) {
        return x.key < y.key;
    }
} Node;

int best_w = 0;

int w[100];  //待选物品的重量
int n;  //题中待选物品的数量
int c; //船的最大载重

int cur_w = 0;  //当前船上的重量
int r;  //当前待选物品的总重量
int step;  //当前层数

void bfs() {
    priority_queue<Node> Q;   //定义一个优先队列
    Node head(r, 0, r, 0);  //从根节点开始遍历

    /* 当遍历到叶节点(每一件货物都讨论了)就结束 */
    while (head.step <= n) {

        step = head.step;
        cur_w = head.cur_w;
        r = head.r - w[step];  //对于剩余货物总重来说,加不加都要减去当前货物
        int maybe = cur_w + w[step]; //如果加上当前货物,船上将有重量

        /* 选择当前物品 (满足约束条件)*/
        if (maybe <= c) {
            best_w = max(best_w, maybe);  //更新最优值
            Node temp(maybe + r, maybe, r, step + 1);
            Q.push(temp);
        }
        /* 不选择当前物品 (满足限界条件)*/
        if (head.key > best_w) {
            Node temp(cur_w + r, cur_w, r, step + 1);
            Q.push(temp);
        }

        /* 出队key最大的 */
        head = Q.top();
        Q.pop();
    }
}

int main() {
    w[0] = 16;
    w[1] = 15;
    w[2] = 15;
    r = 16 + 15 + 15;
    c = 30;
    n = 3;

    bfs();
    cout << best_w << endl;
}

 

 

Guess you like

Origin blog.csdn.net/weixin_43787043/article/details/106217302