Problem description
Give you a backpack with a weight of W and N items. Each item has two attributes: weight and value. The weight of the ith item is wt[i] and the value is val[i]. Now, what is the maximum value you can pack with this back package?
Problem solving ideas
01 knapsack problem is a very classic dynamic programming problem, which can be a good introduction to dynamic programming, and there are many deformation problems related to it
(1) What are the status and choices?
- Status: since items are constantly put into the status, there are two changes - "Backpack Capacity" and optional items
- Choice: the choice is to either install it or not (i.e. 0 and 1)
Therefore, the selection leads to a state change. If you choose to load, it will reduce the capacity of the backpack and the number of selectable items
(2) How to define dp array
Next, define the dp array based on the status and selection. dp array completes dynamic transfer. There is no doubt that the value of dp array must be value. The dynamic planning framework is as follows
The question is about the maximum value that can be loaded when the number of items is N and the backpack capacity is w. then we also define dp array as dp[i][w] (the essence of dynamic programming is the transfer of state, just like building a wall. Each brick and tile above represents a state, and their arrival is closely related to the bricks and tiles below). It means that for the first I items, If the given capacity is w, the maximum value that can be installed is dp[i][w]
The subsequent operation is to deduce each state step by step from the simplest case, and finally return the result when i=N and w=W.
(3)base case
base case is easy to think of. The most extreme and simplest case is naturally i=0, which means no items are selected, and w=0, which means the backpack capacity is 0. Their results are all 0
(4) Frame
So the most original framework is as follows
int dp[N+1][W+1] dp[0][..] = 0 dp[..][0] = 0 for i in [1..N]: for w in [1..W]: dp[i][w] = max( Put the item i Put it in your backpack, Don't put things i Put it in your backpack ) return dp[N][W]
The most difficult part of dynamic planning is dynamic transfer, that is, how to express the above text as code
(5) Dynamic transfer
- If the i-th item is not put in the backpack: obviously, since the i-th item is not put in, the value will not increase and the status will not change, that is, dp[i][w]==dp[i-1][w]
- If the i-th item is put into the backpack: since it is put into the backpack, the capacity in this state will decrease by wt[i], and the value will increase by val[i], so dp[i][w]==dp[i-1][w-wt[i-1]]+val[i-1]
It should be noted that I starts from 1, so i-1 in the indexes of val and WT represents the ith item. So dp[i][w]==dp[i-1][w-wt[i-1]]+val[i-1] means that if the i-th item is loaded, it is necessary to find the maximum value under the limit of residual weight w-wt[i-1], plus the value val[i-1] of the i-th item
code
int knapsack(int W, int N, vector<int>& wt, vector<int>& val) { // The vector is filled with 0, and the base case has been initialized vector<vector<int>> dp(N + 1, vector<int>(W + 1, 0)); for (int i = 1; i <= N; i++) { for (int w = 1; w <= W; w++) { if (w - wt[i-1] < 0) { // The current backpack capacity cannot be loaded. You can only choose not to load the backpack dp[i][w] = dp[i - 1][w]; } else { // Pack or not pack, preferred dp[i][w] = max(dp[i - 1][w - wt[i-1]] + val[i-1], dp[i - 1][w]); } } } return dp[N][W]; }
01 knapsack problem related topics
1: Niuke - find the minimum non composable sum of positive arrays
According to the original knapsack problem, it can be understood as follows: Min is the mass of the lightest item, and sum is the total mass of all items. Suppose there is a knapsack with a capacity range of [min,sum], and len items of different weights
That is, the data in the array is regarded as the weight of items. If these items cannot fill the backpack with a certain capacity (range [min,max]), it means that they cannot form the number of that range
class Solution { public: /** * Minimum non composable sum in positive array * Input: positive array arr * Returns: the smallest non composable sum in a positive array */ int getFirstUnFormedNum(vector<int> arr, int len) { //The range is [min,sum]; int sum=0,min=arr[0]; int i,j; for(int i=0;i<len;i++) { sum+=arr[i]; min=arr[i] < min ? arr[i] : min; } vector<int> dp(sum+1,0); for(i=0;i<len;i++) { for(j=sum;j>=arr[i];j--)//If the backpack capacity is less than the item, it will be ignored directly { if(dp[j] < dp[j-arr[i]]+arr[i])//Yes dp[j]=dp[j-arr[i]]+arr[i]; else//Didn't choose dp[j]=dp[j]; } } //Finally, as long as the weight is not the number of that interval, it must be the result for(i=min;i<=sum;i++) { if(i!=dp[i]) return i; } return sum+1; } };