分支限界法解决最小重量机器设计

350 阅读2分钟

本文是分支限界法的另一个应用,主要解决的的最小重量机器设计问题。

题目描述

设某一个机器由 nn 个零件组成,每个零件都可以从 kk 个不同的供应商处购买,其体积和所需要消耗的价值用 vij,wijv_{ij}, w_{ij} 表示,现在给出最大限制金额 mm,要求在最大限制金额的情况下,求所购买零件的最小体积。

题目首先输入 n,k,mn,k,m,接下来 nn 行每行输入 kk 个数字代表 vi,jv_{i,j},再接下来 nn 行每行输入 kk 个数字代表 wijw_{ij}

题目样例

输入样例

3 3 4  
1 2 3  
3 2 1  
2 2 2  
1 2 3  
3 2 1  
2 2 2

输出样例

4  
1 3 1

题目分析

对定义每个节点的结构体,其包括当前节点的层号 idxidx,已消耗体积 vuv_u,向下所有层的最小消耗体积下界 vdv_d,已消耗价值 wuw_u,向下所有层的最小消耗价值下界 wdw_d,已选择的零件数组 aa,并重载了大于号(后续优先队列的排序)。

计算每层节点的最小选择体积和最小选择价值。

进行最优选择的广度搜素。首先建立根节点并将其置入优先队列。若队列不空,每次提取出 vu+vdv_u + v_d 数值最小的节点,这个节点意味着在目前情况下能够达到的体积已消耗值和下界值中数值最小的节点,即当前来看期望最优的路线,此时节点的最优价值消耗也应满足要求。然后以此为父节点,将其子节点更新数值并加入优先队列,依次递推。当走过全程时,更新答案,在这里,当前节点意味着满足价值条件的最小体积情况,所以答案为最优答案,跳出循环即可。注意对路线数组 aa 的更新。

Accept代码

#include <bits/stdc++.h>

using namespace std;

const int N = 100;
int v[N][N], w[N][N];
int miv[N], miw[N];
int n, k, m;
int ans = 1e9;
vector<int> f;

struct P
{
    int idx;
    int vu, wu;
    int vd, wd;
    vector<int> a;
    
    bool operator> (const P& f)const
    {
        return vu + vd > f.vu + f.vd;
    }
} ;

int main()
{
    cin >> n >> k >> m;
    for (int i = 1; i <= n; i ++)
    {
        miw[i] = 100;
        for (int j = 1; j <= k; j ++)
            cin >> w[i][j], miw[i] = min(miw[i], w[i][j]);
    }

    for (int i = 1; i <= n; i ++)
    {
        miv[i] = 100;
        for (int j = 1; j <= k; j ++)
            cin >> v[i][j], miv[i] = min(miv[i], v[i][j]);
    }
    
    priority_queue<P, vector<P>, greater<P>> q;
    P root; 
    root.idx = 1;
    root.vu = 0, root.wu = 0;
    root.vd = accumulate(miv + 1, miv + 1 + n, 0);
    root.wd = accumulate(miw + 1, miw + 1 + n, 0);
    q.push(root);
    while (!q.empty())
    {
        P t = q.top(); q.pop();
        if (t.wu + t.wd > m) continue;
        if (t.idx == n + 1)
        {
            ans = t.vu + t.vd;
            f = t.a;
            break;
        }
        for (int i = 1; i <= k; i ++)
        {
            P x = t; x.idx ++;
            x.vu += v[t.idx][i], x.vd -= miv[t.idx];
            x.wu += w[t.idx][i], x.wu -= miw[t.idx];
            x.a.push_back(i);
            q.push(x);
        }
    }
    cout << ans << "\n";
    for (auto i : f) cout << i << ' ';
    return 0;
}