简体   繁体   English

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

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

I'm trying to implement a code that lists all possible combinations of a Knapsack problem using recursion.我正在尝试实现一个代码,该代码使用递归列出背包问题的所有可能组合。 I have difficulty with recursion.我在递归上有困难。 I tried to solve it and got nothing, so I did some research and I found a code in Java Python, but I'm having a hard time trying to rewrite that code in C++.我试图解决它但一无所获,所以我做了一些研究,并在 Java Python 中找到了一个代码,但我很难尝试用 C++ 重写该代码。

Here is the solution code, in Java Python:这是 Java Python中的解决方案代码:

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)

I found that code in this link我在此链接中找到了该代码

Here is what I tried to do..这是我试图做的..

#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;

}

With the input:输入:

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

I expect to get the following final result:我希望得到以下最终结果:

[]
[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]

But all I get is arrays filled with 3 and 4 instead of getting all actual solutions.但我得到的只是用 3 和 4 填充的数组,而不是得到所有实际的解决方案。

In short简而言之

There is a major issue in your transcription of the algorithm from python to C++ related to the language semantics related to parameter passing.在您将算法从 python 转录到 C++ 时,存在一个与参数传递相关的语言语义相关的主要问题。

In full details详细信息

When in python you write the following:在 python 中,您编写以下内容:

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

Then list(knapsack) is a copy from the knapsack list.然后list(knapsack)是来自knapsack列表的副本 So the recursive call in the middle leaves the original knapsack unchanged, whereas the second recursive call changes the original knapsack :所以中间的递归调用保持原来的knapsack不变,而第二个递归调用改变了原来的knapsack

print_solutions(current_item + 1, knapsack, current_sum)

In your C++ code however, in both case you work on the original knapsack list (the arrays parameters are passed by references), so that knapsack gets completely messed up:然而,在您的 C++ 代码中,在这两种情况下,您都在处理原始knapsack列表(数组参数通过引用传递),因此knapsack完全搞砸了:

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

How to make it work ?如何使它工作?

Either you create a temporary array and copy knapsack in it, or, much better, you start to use vector , which will make your C++ life much easier (making attention to pass by value or by reference).您可以创建一个临时数组并在其中复制knapsack ,或者更好的是,您开始使用vector ,这将使您的 C++ 生活更轻松(注意按值传递或按引用传递)。

The following version uses a vectors.以下版本使用向量。 The & in the parameter means that it's an argument passed by reference (ie the original vector can be changed).参数中的&表示它是通过引用传递的参数(即可以更改原始向量)。 Note that we do no longer need to pass n , as the vector knows its length, as list do in python:请注意,我们不再需要传递n ,因为向量知道它的长度,就像 Python 中的 list 一样:

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);
    };
};

Here an online demo .这里有一个在线演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM