Python 到 C++:使用递归列出背包所有组合的算法

Python to C++: Algorithm that list all combinations of Knapsack using recursion

我正在尝试实现一个代码,该代码使用递归列出背包问题的所有可能组合。我在递归方面有困难。我试图解决它但一无所获,所以我做了一些研究,我在 Java Python 中找到了一个代码,但我很难尝试用 C++ 重写该代码。

这里是解决代码,在JavaPython:

items = [1,1,3,4,5]
knapsack = []
limit = 7

def print_solutions(current_item, knapsack, current_sum):
    #if all items have been processed print the solution and return:
    if current_item == len(items):
        print knapsack
        return

    #don't take the current item and go check others
    print_solutions(current_item + 1, list(knapsack), current_sum)

    #take the current item if the value doesn't exceed the limit
    if (current_sum + items[current_item] <= limit):
        knapsack.append(items[current_item])
        current_sum += items[current_item]
        #current item taken go check others
        print_solutions(current_item + 1, knapsack, current_sum )

print_solutions(0,knapsack,0)

我在

中找到了该代码

这是我尝试做的..

#include <iostream>
using namespace std;   

void AddItem(int item, int *knapsack) {
    int i = 0;
    while (knapsack[i] != -1)
        i++;    
    knapsack[i] = item;

};
void printKnapsack(int *knapsack, int n) {
    cout << "[";
    for (int i = 0; i < n; i++)
        if (knapsack[i] != -1)
            cout << knapsack[i] << ",";
}

void print_solutions(int current_item, int *knapsack, int current_sum, int *items, int n, int limit) {
    //if all items have been processed print the solution and return
    if (current_item == n - 1) {
        printKnapsack(knapsack, n);
        return;
    };

    //don't take the current item and go check others
    print_solutions(current_item + 1, knapsack, current_sum, items, n, limit);

    //take the current item if the value doesn't exceed the limit
    if (current_sum + items[current_item] <= limit) {
        AddItem(items[current_item], knapsack);
        current_sum += items[current_item];
    };
    //current item taken go check others
    print_solutions(current_item + 1, knapsack, current_sum, items, n, limit);

};

int main() {
    int current_item = 0;
    int current_sum = 0;
    int limit, n;
    cout << "Type the maximum weight ";
    cin >> limit;
    cout << "How many items?  ";
    cin >> n;
    int* knapsack;
    knapsack = new int[10];
    for (int i = 0; i < 10; i++)
        knapsack[i] = -1;
    int * items;
    items = new int[n];

    cout << "Type weights.";
    for (int i = 0; i < n; i++) {
        cin >> items[i];
    };

    print_solutions(0, knapsack, 0, items, n, limit);

    return 0;

}

随着输入:

7                       // limit
5                       // number of items 
1 1 3 4 5               // items

我希望得到以下最终结果:

[]
[5]
[4]
[3]
[3, 4]
[1]
[1, 5]
[1, 4]
[1, 3]
[1]
[1, 5]
[1, 4]
[1, 3]
[1, 1]
[1, 1, 5]
[1, 1, 4]
[1, 1, 3]

但我得到的只是用 3 和 4 填充的数组,而不是得到所有实际的解决方案。

简而言之

您将算法从 python 转录为 C++ 时存在一个主要问题,与参数传递相关的语言语义有关。

详细信息

当在 python 中时,您编写以下内容:

    print_solutions(current_item + 1, list(knapsack), current_sum)

那么 list(knapsack)knapsack 列表中的 copy。所以中间的递归调用保持原来的knapsack不变,而第二次递归调用改变了原来的knapsack

print_solutions(current_item + 1, knapsack, current_sum)

然而,在您的 C++ 代码中,在这两种情况下,您都在处理原始 knapsack 列表(数组参数通过引用传递),因此 knapsack 完全搞砸了:

//don't take the current item and go check others
print_solutions(current_item + 1, knapsack, current_sum, items, n, limit);

如何让它发挥作用?

要么创建一个临时数组并在其中复制 knapsack,要么开始使用 vector 更好,这将使您的 C++ 生活更轻松(注意通过值或参考)。

以下版本使用向量。参数中的 & 表示它是通过引用传递的参数(即可以更改原始向量)。请注意,我们不再需要传递 n,因为向量知道它的长度,就像列表在 python 中所做的那样:

void print_solutions(int current_item, vector<int>& knapsack, int current_sum, const vector<int>& items, int limit) {  

    //if all items have been processed print the solution and return
    if (current_item == items.size() ) {
        printKnapsack(knapsack);
        return;
    };

    //don't take the current item and go check others
    vector<int> knapcopy = knapsack; 
    print_solutions(current_item + 1, knapcopy, current_sum, items, limit);

    //take the current item if the value doesn't exceed the limit
    if (current_sum + items[current_item] <= limit) {
        knapsack.push_back(items[current_item]);
        current_sum += items[current_item];
        //current item taken go check others
        print_solutions(current_item + 1, knapsack, current_sum, items, limit);
    };
};

这里是online demo.