一尘不染

两个袋子的背包算法

algorithm

我发现了为2个背包的背包算法提供伪代码的线程。我试过用C++实现它,但是它不能像预期的那样工作。这是代码:

#include <cstdio>
#define MAX_W1 501
#define MAX_W2 501

int maximum(int a, int b, int c) {
    int max = a>b?a:b;
    return c>max?c:max;
}

int knapsack[MAX_W1][MAX_W2] = {0};

int main() {
    int n, s1, s2, gain, weight; // items, sack1, sack2, gain, cost

    scanf("%d %d %d", &n, &s1, &s2);

    // filing knapsack
    for (int i = 0; i < n; i++) {
        scanf("%d %d", &gain, &weight);

        for (int w1 = s1; w1 >= weight; w1--) {
            for (int w2 = s2; w2 >= weight; w2--) {
                knapsack[w1][w2] = maximum(
                    knapsack[w1][w2],                 // we have best option
                    knapsack[w1 - weight][w2] + gain, // put into sack one
                    knapsack[w1][w2 - weight] + gain  // put into sack two
                );
            }
        }
    }

    int result = 0;

    // searching for result
    for (int i = 0; i <= s1; i++) {
        for (int j = 0; j <= s2; j++) {
            if (knapsack[i][j] > result) {
                result = knapsack[i][j];
            }
        }
    }

    printf("%d\n", result);

    return 0;
}

例如以下输入:

5 4 3
6 2
3 2
4 1
2 1
1 1

我有输出:

13

显然这是错误的,因为我可以将所有物品(第一个袋子中的1,2个放进第二个袋子中,其余的全部放进去),总和为16。对于伪代码错误的任何解释,我将不胜感激。

我没有做太多更新,因为有些人在理解输入格式方面存在问题:

  1. 第一行包含3个数字,如下所示:项目数,袋的容量,袋的容量2
  2. 稍后有n行,每行包含2个数字:收益,第i个项目的成本。
  3. 假设麻袋不能大于500。

阅读 347

收藏
2020-07-28

共1个答案

一尘不染

您使用的算法似乎不正确,因为它只会考虑对象恰好适合两个麻袋的情况。我对您的代码进行了以下更改,并且现在可以正常运行:

#include <algorithm>

using std::max;

int max3(int a, int b, int c) {
    return max(a, max(b, c));
}

for (int w1 = s1; w1 >= 0; w1--) {
    for (int w2 = s2; w2 >= 0; w2--) {
        if (w1 >= weight && w2 >= weight) // either sack has room
        {
            knapsack[w1][w2] = max3(
                knapsack[w1][w2],                 // we have best option
                knapsack[w1 - weight][w2] + gain, // put into sack one
                knapsack[w1][w2 - weight] + gain  // put into sack two
            );
        }
        else if (w1 >= weight) // only sack one has room
        {
            knapsack[w1][w2] = max(
                knapsack[w1][w2],                 // we have best option
                knapsack[w1 - weight][w2] + gain  // put into sack one
            );
        }
        else if (w2 >= weight) // only sack two has room
        {
            knapsack[w1][w2] = max(
                knapsack[w1][w2],                 // we have best option
                knapsack[w1][w2 - weight] + gain  // put into sack two
            );
        }
    }
}
2020-07-28