[英]Find which items are taken in knapsack
solving the knapsack problem recursively, I want to know which items (item's weight) are taken in the bag that gives the maximum value. 递归解决背包问题,我想知道哪些物品(物品的重量)取在了具有最大值的包中。 so far I have this:
到目前为止,我有这个:
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;
}
consider n=4 and maximum weight (W) = 30 考虑n = 4并且最大重量(W)= 30
let weights be : 30 10 20 5 权重为:30 10 20 5
and values : 100 50 60 10 和值:100 50 60 10
but this code outputs: 20 5 20 10 5 但是此代码输出:20 5 20 10 5
I just want to output 10 and 20. 我只想输出10和20。
also I have tried to define a bool array with default values of false and its nth element changes to true if c==a occurs but this won't give the correct result as well. 我也试图定义一个默认值为false的布尔数组,并且如果出现c == a,其第n个元素将变为true,但这也无法给出正确的结果。
I'm supposed to do it recursively. 我应该递归地做。
Your basic algorithm doesn't work. 您的基本算法无效。 You can't do the printing while you test different combinations.
测试不同的组合时无法进行打印。
However, first you must fix a bug: 但是,首先必须修复一个错误:
cout<<weight[n-1]<<endl; // n-1 instead of n
Your algorithm does this: 您的算法会执行以下操作:
a = value[3] + thief(30-weight[3], weight, value, 3); // Use item 3
b = thief(30, weight, value, 3); // Don't use item 3
The second line will lead to 第二行将导致
a = value[2] + thief(30-weight[2], weight, value, 2); // Use item 2
b = thief(30, weight, value, 2); // Don't use item 2
The second line will lead to 第二行将导致
a = value[1] + thief(30-weight[1], weight, value, 1); // Use item 1
b = thief(30, weight, value, 1); // Don't use item 1
The second line will lead to 第二行将导致
a = value[0] + thief(30-weight[0], weight, value, 0); // Use item 0
b = thief(30, weight, value, 0); // Don't use item 0
This causes 这导致
a = 30
b = 0
so your code will select item 0
and print 30
but that is a bug! 因此您的代码将选择
item 0
并打印30
但这是一个错误!
So as I stated in the start: You can't do the printing while you test different combinations. 因此,正如我在开始时所说:测试不同的组合时,您将无法进行打印。
Instead you need to keep track of which elements you use in the different combinations and only keep the "best". 相反,您需要跟踪在不同组合中使用哪些元素,并且仅保持“最佳”状态。
I haven't tested the code below but I think you can do it like this (assuming your code calculates the best combination correctly): 我尚未测试以下代码,但我想您可以这样做(假设您的代码正确计算出最佳组合):
#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;
}
Finally notice - your brute force method is very expensive in terms of execution time in the start value for n is high. 最后要注意-在执行时间方面,n的起始值很高,因此蛮力方法非常昂贵。 There are much better ways to solve this problem.
有很多更好的方法可以解决此问题。
can you write the code in c? 你可以用c编写代码吗? I wrote this but didn't work.
我写了这个,但是没有用。 (I think the difference is in the bold)
(我认为区别在于粗体)
int knapSack(int W, int wt[], int val[], int n, int arr[])
{
int x, y, c, j, arr1[50], arr2[50];
// Base Case
if (n == 0 || W == 0)
return 0;
// If weight of the nth item is more than Knapsack capacity W, then
// this item cannot be included in the optimal solution
if (wt[n - 1] > W)
return knapSack(W, wt, val, n - 1, arr2);
// Return the maximum of two cases:
// x nth item included
// y not included
**arr1[n - 1] = val[n - 1];**
x = val[n - 1] + knapSack(W - wt[n - 1], wt, val, n - 1, arr1);
//copyArr(arr, out, n);
y = knapSack(W, wt, val, n - 1, arr2);
if (x > y)
c = x;
else
c = y;
if (c == x)
for (j = 0; j < 50; j++)
arr[j] = arr1[j];
else
for (j = 0; j < 50; j++)
arr[j] = arr2[j];
return c;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.