c++ - 查找背包中带了哪些元素

标签 c++ recursion knapsack-problem

递归求解背包问题,我想知道袋子里拿了哪些元素(元素的重量)给出最大值。 到目前为止我有这个:

int MAX(int a, int b) { return (a > b) ? a : b ; }
int thief(int W, int weight[], int value[], int n)
{
    int a,b,c;
    //basecase:
    if(n == 0 || weight <= 0) return 0;
    // each item's weight can't be more than W:
    if(weight[n-1] > W){
        return thief(W, weight, value, n-1);}

    a=value[n-1] + thief(W-weight[n-1], weight, value, n-1);// a: nth item included
    b=thief(W, weight, value, n-1);// b:nth item not included
    c= MAX(a,b);//answer is the maximum of situation a and b
    if (c==a) { //if situation a occurs then nth item is included
        cout<<weight[n]<<endl;
    }
    return c;


 }

考虑 n=4 且最大重量 (W) = 30
让权重为:30 10 20 5
和值:100 50 60 10
但是这段代码输出:20 5 20 10 5
我只想输出 10 和 20。
我还尝试定义一个默认值为 false 的 bool 数组,如果 c==a 发生,它的第 n 个元素会更改为 true,但这也不会给出正确的结果。
我应该递归地做。

最佳答案

您的基本算法不起作用。您无法在测试不同组合时进行打印。

但是,首先你必须修复一个错误:

    cout<<weight[n-1]<<endl; // n-1 instead of n 

您的算法执行此操作:

a = value[3] + thief(30-weight[3], weight, value, 3); // Use item 3
b = thief(30, weight, value, 3);                      // Don't use item 3

第二行会导致

a = value[2] + thief(30-weight[2], weight, value, 2); // Use item 2
b = thief(30, weight, value, 2);                      // Don't use item 2

第二行会导致

a = value[1] + thief(30-weight[1], weight, value, 1); // Use item 1
b = thief(30, weight, value, 1);                      // Don't use item 1

第二行会导致

a = value[0] + thief(30-weight[0], weight, value, 0); // Use item 0
b = thief(30, weight, value, 0);                      // Don't use item 0

这导致

a = 30
b = 0

因此您的代码将选择 item 0 并打印 30 但这是一个错误!

因此,正如我在开始时所说:您无法在测试不同组合时进行打印。

相反,您需要跟踪您在不同组合中使用了哪些元素,并且只保留“最佳”元素。

我没有测试下面的代码,但我认为你可以这样做(假设你的代码正确计算出最佳组合):

#include <vector>

// The vector v is used for holding the index of the items selected.
// The caller must supply a vector containing the items included so far.
// This function will test whether item "n-1" shall be included or
// excluded. If item "n-1" is included the index is added to the vector.

int thief(int W, int weight[], int value[], int n, vector<int>& v) // Added vector
{
    vector<int> v1, v2; // Vector to hold elements of the two combinations
    int a,b,c;
    //basecase:
    if(n == 0 || weight <= 0) return 0;
    // each item's weight can't be more than W:
    if(weight[n-1] > W){
        return thief(W, weight, value, n-1, v2);}

    v1.push_back(n-1); // Put n-1 in vector v1 and pass the vector v1
    a=value[n-1] + thief(W-weight[n-1], weight, value, n-1, v1);// a: nth item included

    // Don't put anything in v2 but pass the vector v2
    b=thief(W, weight, value, n-1, v2);// b:nth item not included
    c= MAX(a,b);//answer is the maximum of situation a and b
    if (c==a) { //if situation a occurs then nth item is included

//            cout<<weight[n-1]<<endl;

        // Copy elements from v1 to v
        for (auto e : v1)
        {
                v.push_back(e);
        }
    }
    else
    {
        // Copy elements from v2 to v
        for (auto e : v2)
        {
                v.push_back(e);
        }
    }
    return c;


 } 

int main() {
    vector<int> v;
    int weight[4] = {30, 10, 20, 5};
    int value[4] = {100, 50, 60, 10};
    cout << "result=" << thief(30, weight, value, 4, v) << endl;

    // Print the elements used
    for (auto e : v)
    {
        cout << "elem=" << e << endl;
    }
    return 0;
}

最后请注意 - 就执行时间而言,您的蛮力方法非常昂贵,因为 n 的起始值很高。有很多更好的方法可以解决这个问题。

关于c++ - 查找背包中带了哪些元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34462059/

相关文章:

c++ - 编译简单的C++应用程序时出错

c++ - 具有整数参数的模板的部分特化

c++ - Posix 线程通信 Linux

recursion - F# 中的递归对象?

Java递归洪水填充算法的问题

c - 一个做出改变的案例(某种程度上)。找到权重的最小组成

algorithm - 0-1 背包动态规划解法行不通

c++ - 仅 header 库循环依赖

javascript - JavaScript 中的洪水填充算法 - 太多递归

algorithm - 将列表分成两部分,它们的总和彼此最接近