【问题标题】:Python to C++: Algorithm that list all combinations of Knapsack using recursionPython 到 C++:使用递归列出所有背包组合的算法
【发布时间】:2022-05-18 23:19:12
【问题描述】:

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

这是解决方案代码,在 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)

我在 link 中找到了该代码

这是我尝试做的..

#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 填充的数组,而不是得到所有实际的解决方案。

【问题讨论】:

  • 那不是java,那是python
  • 对不起!我修好了。

标签: python c++ algorithm recursion knapsack-problem


【解决方案1】:

总之

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

详细介绍

在 python 中,你可以编写以下代码:

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

那么list(knapsack)copy 来自knapsack 列表。所以中间的递归调用保持原来的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++ 生活更轻松(注意按值传递或按引用传递)。

以下版本使用向量。参数中的&amp; 表示它是通过引用传递的参数(即可以更改原始向量)。请注意,我们不再需要传递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

【讨论】:

  • 非常感谢!一旦你建议使用向量,我就研究了一点,并试图让它发挥作用。我很高兴现在看到您的代码:我非常接近!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-24
  • 2014-08-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多