The Knapsack problem

本文介绍了一个经典的背包问题,并通过动态规划的方法求解。利用ItemxWeight数组逐步填充最大价值,最终得出背包容量为10时的最大价值为90。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

I found the Knapsack problem tricky and interesting at the same time. I am sure if you are visiting this page, you already know the problem statement but just for the sake of completion :

Problem:

Given a Knapsack of a maximum capacity of W and N items each with its own value and weight, throw in items inside the Knapsack such that the final contents has the maximum value. Yikes !!!

 
 
 
Knapsack.svg

Here’s the general way the problem is explained – Consider a thief gets into a home to rob and he carries a knapsack. There are fixed number of items in the home – each with its own weight and value – Jewellery, with less weight and highest value vs tables, with less value but a lot heavy. To add fuel to the fire, the thief has an old knapsack which has limited capacity. Obviously, he can’t split the table into half or jewellery into 3/4ths. He either takes it or leaves it.

Example :
1 Knapsack Max weight     :       W = 10 (units)
2  
3     Total items             :       N = 4
4  
5     Values of items         :       v[] = {10403050}
6  
7     Weight of items         :       w[] = {5463}

A cursory look at the example data tells us that the max value that we could accommodate with the limit of max weight of 10 is 50 + 40 = 90 with a weight of 7.

Approach:

The way this is optimally solved is using dynamic programming – solving for smaller sets of knapsack problems and then expanding them for the bigger problem.

Let’s build an Item x Weight array called V (Value array):

1 V[N][W] = 4 rows * 10 columns

Each of the values in this matrix represent a smaller Knapsack problem.

Base case 1 : Let’s take the case of 0th column. It just means that the knapsack has 0 capacity. What can you hold in them? Nothing. So, let’s fill them up all with 0s.

Base case 2 : Let’s take the case of 0 row. It just means that there are no items in the house. What do you do hold in your knapsack if there are no items. Nothing again !!! All zeroes.

Varray0

Solution:

  1. Now, let’s start filling in the array row-wise. What does row 1 and column 1 mean? That given the first item (row), can you accommodate it in the knapsack with capacity 1 (column). Nope. The weight of the first item is 5. So, let’s fill in 0. In fact, we wouldn’t be able to fill in anything until we reach the column 5 (weight 5).
  2. Once we reach column 5 (which represents weight 5) on the first row, it means that we could accommodate item 1. Let’s fill in 10 there (remember, this is a Value array):

     
    Varray1

  3. Moving on, for weight 6 (column 6), can we accommodate anything else with the remaining weight of 1 (weight – weight of this item => 6 – 5). Hey, remember, we are on the first item. So, it is kind of intuitive that the rest of the row will just be the same value too since we are unable to add in any other item for that extra weight that we have got.

     
    Varray2

  4. So, the next interesting thing happens when we reach the column 4 in third row. The current running weight is 4.

We should check for the following cases.

  1. Can we accommodate Item 2 – Yes, we can. Item 2’s weight is 4.
  2. Is the value for the current weight is higher without Item 2? – Check the previous row for the same weight. Nope. the previous row* has 0 in it, since we were not able able accommodate Item 1 in weight 4.
  3. Can we accommodate two items in the same weight so that we could maximize the value? – Nope. The remaining weight after deducting the Item2’s weight is 0.

Varray3

Why previous row?

Simply because the previous row at weight 4 itself is a smaller knapsack solution which gives the max value that could be accumulated for that weight until that point (traversing through the items).

Exemplifying,

  1. The value of the current item = 40
  2. The weight of the current item = 4
  3. The weight that is left over = 4 – 4 = 0
  4. Check the row above (the Item above in case of Item 1 or the cumulative Max value in case of the rest of the rows). For the remaining weight 0, are we able to accommodate Item 1? Simply put, is there any value at all in the row above for the given weight?

The calculation goes like so :

  1. Take the max value for the same weight without this item:
    1 previous row, same weight = 0
    2  
    3 => V[item-1][weight]
  2. Take the value of the current item + value that we could accommodate with the remaining weight:
    1 Value of current item
    2 + value in previous row with weight 4 (total weight until now (4) - weight of the current item (4))
    3  
    4 => val[item-1] + V[item-1][weight-wt[item-1]]

    Max among the two is 40 (0 and 40).

  3. The next and the most important event happens at column 9 and row 2. Meaning we have a weight of 9 and we have two items. Looking at the example data we could accommodate the first two items. Here, we consider few things:
    1 1. The value of the current item = 40
    2 2. The weight of the current item = 4
    3 3. The weight that is left over = 9 4 5
    4 4. Check the row above.  At the remaining weight 5, are we able to accommodate Item 1.

     
    Varray4

So, the calculation is :

  1. Take the max value for the same weight without this item:
    1 previous row, same weight = 10
  2. Take the value of the current item + value that we could accumulate with the remaining weight:
    1 Value of current item (40)
    2 + value in previous row with weight 5 (total weight until now (9) - weight of the current item (4))
    3  
    4 = 10

    10 vs 50 = 50.

At the end of solving all these smaller problems, we just need to return the value at V[N][W] – Item 4 at Weight 10:

Varray5

Complexity

Analyzing the complexity of the solution is pretty straight-forward. We just have a loop for W within a loop of N => O (NW)

Implementation:

Here comes the obligatory implementation code in Java:

01 class Knapsack {
02  
03     public static void main(String[] args) throws Exception {
04         int val[] = {10, 40, 30, 50};
05         int wt[] = {5, 4, 6, 3};
06         int W = 10;
07  
08         System.out.println(knapsack(val, wt, W));
09     }
10  
11     public static int knapsack(int val[], int wt[], int W) {
12  
13         //Get the total number of items.
14         //Could be wt.length or val.length. Doesn't matter
15         int N = wt.length;
16  
17         //Create a matrix.
18         //Items are in rows and weight at in columns +1 on each side
19         int[][] V = new int[N + 1][W + 1];
20  
21  
22         //What if the knapsack's capacity is 0 - Set
23         //all columns at row 0 to be 0
24         for (int col = 0; col <= W; col++) {
25             V[0][col] = 0;
26         }
27  
28         //What if there are no items at home. 
29         //Fill the first row with 0
30         for (int row = 0; row <= N; row++) {
31             V[row][0] = 0;
32         }
33  
34         for (int item=1;item<=N;item++){
35  
36             //Let's fill the values row by row
37             for (int weight=1;weight<=W;weight++){
38  
39                 //Is the current items weight less
40                 //than or equal to running weight
41                 if (wt[item-1]<=weight){
42  
43 //Given a weight, check if the value of the current
44 //item + value of the item that we could afford
45 //with the remaining weight is greater than the value
46 //without the current item itself
47                     V[item][weight]=Math.max (val[item-1]+V[item-1][weight-wt[item-1]], V[item-1][weight]);
48                 }
49                 else {
50 //If the current item's weight is more than the
51 //running weight, just carry forward the value
52 //without the current item
53                     V[item][weight]=V[item-1][weight];
54                 }
55             }
56  
57         }
58  
59         //Printing the matrix
60         for (int[] rows : V) {
61             for (int col : rows) {
62  
63                 System.out.format("%5d", col);
64             }
65             System.out.println();
66         }
67  
68         return V[N][W];
69  
70     }
71  
72 }
The 0-1 Knapsack Problem is a classic optimization problem in computer science and mathematics. The problem is as follows: Given a set of items, each with a weight and a value, determine the items 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. The 0-1 indicates that each item can only be included once or not at all. This problem can be solved using dynamic programming. We can create a two-dimensional array where the rows represent the items and the columns represent the weight limit. For each item and weight limit, we can calculate the maximum value that can be obtained by either including the item or excluding it. We can then fill in the array row by row until we reach the final row, which represents the optimal solution. Here is an example implementation of the 0-1 Knapsack Problem in Java: ``` public class Knapsack { public static int knapsack(int[] values, int[] weights, int limit) { int[][] dp = new int[values.length + 1][limit + 1]; for (int i = 1; i <= values.length; i++) { for (int j = 1; j <= limit; j++) { if (weights[i-1] > j) { dp[i][j] = dp[i-1][j]; } else { dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-weights[i-1]] + values[i-1]); } } } return dp[values.length][limit]; } public static void main(String[] args) { int[] values = {60, 100, 120}; int[] weights = {10, 20, 30}; int limit = 50; int result = knapsack(values, weights, limit); System.out.println("Maximum value: " + result); } } ``` In this example, we have three items with values of 60, 100, and 120 and weights of 10, 20, and 30, respectively. We want to find the maximum value we can obtain with a weight limit of 50. The result is 220, which indicates that we should select items 2 and 3 to maximize the value while staying under the weight limit.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值