Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knapsack but exact weight

Is there a algorithm to determine a knapsack which has an exact weight W? I.e. it's like the normal 0/1 knapsack problem with n items each having weight w_i and value v_i. Maximise the value of all the items, however the total weight of the items in the knapsack need to have exactly weight W!

I know the "normal" 0/1 knapsack algorithm but this could also return a knapsack with less weight but higher value. I want to find the highest value but exact W weight.

Here is my 0/1 knapsack implementation:

public class KnapSackTest {
    public static void main(String[] args) {
        int[] w = new int[] {4, 1, 5, 8, 3, 9, 2};  //weights
        int[] v = new int[] {2, 12, 8, 9, 3, 4, 3}; //values

        int n = w.length;
        int W = 15; // W (max weight)

        int[][] DP = new int[n+1][W+1];

        for(int i = 1; i < n+1; i++) {
            for(int j = 0; j < W+1; j++) {
                if(i == 0 || j == 0) {
                    DP[i][j] = 0;
                } else if (j - w[i-1] >= 0) {
                    DP[i][j] = Math.max(DP[i-1][j], DP[i-1][j - w[i-1]] + v[i-1]);
                } else {
                    DP[i][j] = DP[i-1][j];
                }
            }
        }
        System.out.println("Result: " + DP[n][W]);
    }
}

This gives me:

Result: 29

(Just ask if anything is unclear in my question!)

like image 822
zutru Avatar asked Dec 02 '17 14:12

zutru


People also ask

What is the solution to the knapsack problem?

The most obvious solution to this problem is brute force recursive. This solution is brute-force because it evaluates the total weight and value of all possible subsets, then selects the subset with the highest value that is still under the weight limit.

What is a 0 1 knapsack problem?

The 0/1 knapsack problem means that the items are either completely or no items are filled in a knapsack. For example, we have two items having weights 2kg and 3kg, respectively. If we pick the 2kg item then we cannot pick 1kg item from the 2kg item (item is not divisible); we have to pick the 2kg item completely.

What is knapsack problem explain?

The knapsack problem is a problem in combinatorial optimization: Given a set of items, each with a weight and a value, determine the number of each item to include in a collection so that the total weight is less than or equal to a given limit and the total value is as large as possible.

How many types of knapsack problems are there?

In this problem, we are given a set of items having different weights and values. We have to find the optimal solution considering all the given items. There are three types of knapsack problems : 0-1 Knapsack, Fractional Knapsack and Unbounded Knapsack.

What is the total value of the items in the knapsack?

Items cannot be broken and an item with weight X takes X capacity of the knapsack. We take objects ‘1’ and ‘3’. The total value we get is (30 + 60) = 90. Recommended: Please try your approach on {IDE} first, before moving on to the solution.

How to get exact weight knapsack from DP?

You get exact weight knapsack by changing only the initial dp state, not the algorithm itself. The rest stays as in your question. By simply setting DP [i] [j] = -infinity in your last else clause it will do the trick. The ides behind it is to slightly change the recursive formula definition to calculate:

What is the complexity of the 0-1 knapsack problem?

Time Complexity: O (2 n ). As there are redundant subproblems. Auxiliary Space : O (1). As no extra data structure has been used for storing values. Since subproblems are evaluated again, this problem has Overlapping Sub-problems property. So the 0-1 Knapsack problem has both properties (see this and this) of a dynamic programming problem.

How do you solve the knapsack problem in Python?

Approach: The traditional famous 0-1 knapsack problem can be solved in O (N*C) time but if the capacity of the knapsack is huge then a 2D N*C array can’t make be made. Luckily, it can be solved by redefining the states of the dp. Let’s have a look at the states of the DP first.


2 Answers

Actually, the accepted answer is wrong, as found by @Shinchan in the comments.

You get exact weight knapsack by changing only the initial dp state, not the algorithm itself.

The initialization, instead of:

            if(i == 0 || j == 0) {
                DP[i][j] = 0;
            }

should be:

            if (j == 0) {
                DP[i][j] = 0;
            } else if (i == 0 && j > 0) { // obviously `&& j > 0` is not needed, but for clarity
                DP[i][j] = -inf;
            }

The rest stays as in your question.

like image 131
Michal Rus Avatar answered Oct 16 '22 16:10

Michal Rus


By simply setting DP[i][j] = -infinity in your last else clause it will do the trick.

The ides behind it is to slightly change the recursive formula definition to calculate:

  • Find the maximal value with exactly weight j up to item i.

Now, the induction hypothesis will change, and the proof of correctness will be very similar to regular knapsack with the following modification:

DP[i][j-weight[i]] is now the maximal value that can be constructed with exactly j-weight[i], and you can either take item i, giving value of DP[i][j-weight[i]], or not taking it, giving value of DP[i-1][j] - which is the maximal value when using exactly weight j with first i-1 items.

Note that if for some reason you cannot construct DP[i][j], you will never use it, as the value -infinity will always discarded when looking for MAX.

like image 22
amit Avatar answered Oct 16 '22 18:10

amit