algorithm - 从不同群体中挑选的背包

标签 algorithm knapsack-problem

我有一个背包问题的变体,我正在努力寻找有效的解决方案。

假设您有多个项目组。每个组可以有任意数量的项目,每个项目都有一个值和权重。问题是找到具有最大总值(value)、重量 < 某个限制的项目集,并且(棘手的部分)只有包含每个组中的一个项目的集合才有效。

也就是说,假设您有数百件元素可供挑选,但您必须拿走一个三明治、一份饮料、一份零食、一个手电筒等。不仅您不能从任何一组中拿取超过一件,而且如果有 g 个组,那么您必须在一天结束时得到恰好 g 个项目。

看起来这应该比基本问题做起来更快,因为很多组合都是无效的,但我正在努力寻找解决方案。

最佳答案

C++ 示例代码。该函数返回最大可实现值,如果不存在可行的解决方案,则返回 -1。它在 O(n * max_weight) 中运行,其中 n 是计算所有组的项目总数,max_weight 是重量限制。复杂度本质上与解决原始背包问题的经典算法相同。该代码实现了 Evgeny Kluev 的回答中的算法。

int CalcMaxValue(const std::vector<std::vector<int>>& weight,
                 const std::vector<std::vector<int>>& value,
                 int max_weight) {
    std::vector<int> last(max_weight + 1, -1);
    if (weight.empty()) return 0;
    for (int i = 0; i < weight[0].size(); ++i) {
        if (weight[0][i] > max_weight) continue;
        last[weight[0][i]] = std::max(last[weight[0][i]], value[0][i]);
    }
    std::vector<int> current(max_weight + 1);
    for (int i = 1; i < weight.size(); ++i) {
        std::fill(current.begin(), current.end(), -1);
        for (int j = 0; j < weight[i].size(); ++j) {
            for (int k = weight[i][j]; k <= max_weight; ++k) {
                if (last[k - weight[i][j]] < 0) continue;
                current[k] = std::max(current[k], last[k - weight[i][j]] + value[i][j]);
            }
        }
        std::swap(current, last);
    }    
    return *std::max_element(last.begin(), last.end());
}

关于algorithm - 从不同群体中挑选的背包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29729609/

相关文章:

algorithm - 来自(可能非常大的)列表的非空分组的不同总和数

c++ - C++提高了检查BST是否高度平衡的效率?

algorithm - 多选背包

java - 背包算法,大容量

python - 没有重复的背包 : Maximum Amount of Gold - Python code question

algorithm - 如何确定两个中最快的排序算法?

python - 用python中的Pillow替换动态图像中的同一行像素

algorithm - 弗洛伊德·沃歇尔(Floyd Warshall)受到限制

algorithm - 如何用 2 个麻袋解决背包算法的这种变体?

algorithm - 以最小代价划分为n个bins