Reputation: 353
The following code should be returning 16 as far as I can tell but for some reason, it returns 10. Does anyone know what my bug might be? Basically it's the Knapsack problem in Java and I've ran through the whole code on paper and it seems to return the right answer to me but I cannot figure out why when it's properly run, it returns back 10.
Any help would be much appreciated. Thanks!
import java.util.Stack;
public class knapsackProblem
{
public static int optimalValue(Stack<item> items, int totalWeight)
{
if (items.isEmpty())
return 0;
int value = items.peek().value;
int weight = items.peek().weight;
items.pop();
if (totalWeight<weight)
return optimalValue(items, totalWeight);
return Math.max(optimalValue(items,totalWeight), value + optimalValue(items, totalWeight-weight));
}
public static void main(String args[])
{
int knapsackWeight = 15;
Stack<item> items = new Stack<item>();
items.push(new item(7,10));
items.push(new item(3,6));
System.out.println(optimalValue(items, knapsackWeight));
}
}
class item
{
public int weight;
public int value;
public item(int aWeight, int aValue)
{
weight = aWeight;
value = aValue;
}
}
Upvotes: 1
Views: 126
Reputation: 31689
I haven't gone through the whole algorithm, but an obvious problem is that every time you call optimalValue
on a Stack
, it will pop one or more items from the stack. But a Stack
, and the items in the stack, are objects, which means they're passed around by reference. So in this line:
return Math.max(optimalValue(items,totalWeight), value + optimalValue(items, totalWeight-weight));
This calls optimalValue
twice. The first time you call it with items
as a parameter, optimalValue
will pop one or more elements from items
. Then the statement calls optimalValue
again with items
as a parameter--and this will NOT use the same items
stack that you passed to the first optimalValue
call, but it will use the items
with the already-popped-off items still popped off (from the first call). I really doubt this is what you want. If you do things this way, then at some point I think you'll have to make a copy of your Stack
. Or you'll need to rethink things and do it a different way (maybe you can use an array or ArrayList
, so that the items aren't actually popped off but you could pass a "starting index" from one optimalValue
call to the recursive call).
I don't know whether there are other problems with your solution in addition to this one.
Upvotes: 0
Reputation: 2785
Your Stack
is being modified across the calls. So a line like
return Math.max(optimalValue(items,totalWeight), value + optimalValue(items, totalWeight-weight));
will have two different copies of items for each call. Not what you want.
Instead of using Stack
, try changing things around to use an ArrayList
. Then pass your index of which item you're evaluating into the optimalValue
method instead. This should help you work through the items correctly.
Upvotes: 1