Machine design (mountain climbing)

Keywords: Algorithm data structure Graph Theory

Title Description: let a machine be controlled by n It consists of two parts, and each part can be m From different suppliers. supplier j Supplied parts i With weight Wij And price Cij . Design an algorithm to solve the total price does not exceed the upper limit c The minimum weight of the machine. (design a branch and bound algorithm for solving the optimal solution, describe the algorithm strategy and write pseudo code)
• Input: number of parts n , supply Quotient number m . matrix [ 𝑤 𝑖𝑗 ]〖[w〗_ij] [ 𝑐 𝑖𝑗 ]〖[c〗_ij] ( 0 ≤ 𝑖 ≤ 𝑚 ,0≤ 𝑗 ≤ 𝑛0≤i≤m,0≤j≤n ), Means that the second i Third vendor j The weight of each component is 𝑤 𝑖𝑗 ,w_ij, The price is c 𝑖𝑗 . Price c_ij . Price upper bound C .
• Output: best_ choice Array, best_choice [ i ]=j explain The first 𝑖 individual parts yes from The first 𝑗 individual supplier Where? Bought , indicating that the i-th part was purchased from the j-th supplier,

Construct subset tree  

• You can make a node in the tree represent the result of a selection. The root node is not selected, that is 𝑥 𝑖𝑗 Full x_ij full by 0 . A node will be derived m The child node represents its next component from m From one supplier.

  pruning strategy

1. For a derived child node, if the sum of the price of the currently selected item and the minimum price of the unselected item is greater than C, it will be cut directly (for the price)

2. Another global variable is bestw, which records the minimum weight of the nodes (the sum of prices is less than C) that have all been selected and have not been pruned. For a derived child node, if the sum of the weight of the selected item and the minimum weight of the unselected item is greater than bestw, it can also be cut directly. (for weight)

Use the mountain climbing method according to the pruning strategy, because it can determine the bestw fastest to prune better.

Implement pruning strategy

• Take the price as an example, we need to know conveniently The sum of the minimum prices of unselected items Deal with it first [ 𝑐 𝑖𝑗 ] .〖[c〗_ij]. We subtract the minimum value of this column from each column. The sum of the subtracted values is the lower bound of the price. After each choice, the price is actually the lower bound of the price. When all choices are made, the lower bound is the upper bound, which is the price. Therefore, this treatment does not affect the treatment, but can get good results The sum of the minimum prices of unselected items to facilitate pruning
• The same is true for weight.
summary
• The information contained in each node in the tree is the lower bound of price cost , lower bound of weight weight , and unselected items array X[n] .
• root node X[n] The lower bound of price and weight is the initial value
• When X If empty, stop.
• Cost>c, or weight> bestw , prune.
• Mountain climbing expansion, priority expansion Node with small lower bound of price
• still more Preprocessing price, weight array
#include <iostream>
#include <queue>
#include <stack>
using namespace std;
#define num_of_project 2 / / number of parts
#define num_of_trade 3 / / number of suppliers
int w[num_of_trade][num_of_project];//Component is column, supplier is row, weight matrix
int c[num_of_trade][num_of_project];//Parts are columns, suppliers are rows, and price matrix
int best_choice[num_of_project];//Component is column, supplier is row, selection matrix
int bestw;
int C;//Upper bound of price

typedef struct node{
    int cost;//Price
    int weight;//For weight, the stack is last in first out. Because the mountain climbing method selects the small weight, the smaller the weight should be later in and be preferentially expanded. Therefore, the larger the weight in the priority queue, the more first in the stack. According to the weight in the priority queue, the larger the weight, the more ahead, and the greater the priority
    int choice[num_of_project];//Indicates which supplier is selected for the ith part
    queue<int> X;//Unselected items, queue is convenient for access
}node;

bool operator<(node a, node b)
{
    return a.weight < b.weight;//weight maximum priority
}

void init(node* child, node* parent) {
    child->cost = parent->cost;
    child->weight = parent->weight;
    child->X = parent->X;
    
}

void printk(int p[3][3]) {
    for (int i = 0; i < num_of_trade; i++) {
        for (int j = 0; j < num_of_project; j++) {
            cout << p[i][j]<<"  ";
        }
        cout << '\n';
    }
}


stack<node> S;//Maintain nodes and realize mountain climbing method

int main()
{
    cin >> C;
    for (int i = 0; i < num_of_trade; i++) {
        for (int j = 0; j < num_of_project; j++) {
            cin >> w[i][j];
            cin>> c[i][j];
        }
    }
    
    int cost_down = 0, weight_down = 0;//Price, weight, lower bound
    for (int i = 0; i < num_of_project; i++) {
        int cost_min = c[0][i], weight_min = w[0][i];//The lowest price and weight provided by each item supplier
        for (int j = 0; j < num_of_trade; j++) {
            if (cost_min > c[j][i]) {
                cost_min = c[j][i];
            }
            if (weight_min > w[j][i]) {
                weight_min = w[j][i];
            }
        }
        cost_down += cost_min;
        weight_down += weight_min;
        for (int j = 0; j < num_of_trade; j++) {
            w[j][i] -= weight_min;
            c[j][i] -= cost_min;
        }
    }//Deal with every item
    node parent_of_all;
    parent_of_all.cost = cost_down;
    parent_of_all.weight = weight_down;
    for (int i = 0; i < num_of_project; i++) {
        parent_of_all.X.push(i);
        
    }
    S.push(parent_of_all);
    bestw = 0x7fffffff;//The maximum value of int indicates that the minimum weight has not been found at the beginning
    while (!S.empty()) {
        priority_queue<node> q;
        node parent = S.top();
        S.pop();
        for (int i = 0; i < num_of_trade; i++) {
            node child;
            init(&child, &parent);
            int next_project = child.X.front();
            child.X.pop();
            child.cost += c[i][next_project];
            child.weight += w[i][next_project];
            child.choice[next_project] = i;
            if (child.cost > C)continue;//For price
            if (child.weight >= bestw)continue;//For the weight, it is equal to cutting faster
            if (child.X.empty()) {
                if (child.weight < bestw) {
                    bestw = child.weight;
                    for (int i = 0; i < num_of_project; i++) {
                        best_choice[i] = child.choice[i];
                    }
                }
                continue;
            }
            q.push(child);//High priority will be put into the stack by the first out team
        }//To get the next from the i-th supplier_ Project contains items, with parts as columns and suppliers as rows
        while (!q.empty()) {
            S.push(q.top());
            q.pop();
        }
    }
    for (int i = 0; i < num_of_project; i++) {
        cout << best_choice[i] << "  ";
    }
    cout << endl;
    cout << bestw;

}

Posted by ptolomea on Sun, 28 Nov 2021 13:15:28 -0800