Dynamic programming-01 knapsack problem analysis

Problem Description

There are n items, and they have their own volume and value. Given a backpack with a total volume of W, how can the items in the backpack have the largest sum of value?

i (item number) 1 2 3 4
w (volume) 2 3 4 5
v (value) 3 4 5 6

Idea overview

Multi-step decision problem -> sub-problem definition -> recursive expression -> repeated redundant sub-problems

The 01 knapsack problem can be multi-step decision-making. Each time you choose whether to put an item into the backpack, 0 means not to put in, and 1 means to put in. Then we can get the following recurrence expression:
Insert picture description here
fill in the table to fill in all the solved sub The answer to the question is recorded, and the sub-questions that need to be used in the new question can be extracted directly, avoiding double calculation and saving time. Therefore, after the problem satisfies the principle of optimality, the core of solving the problem with dynamic programming is to fill in the form , After filling in the table, the optimal solution will be found.

Solution

Dynamic programming 1

  1. Abstract the knapsack problem ( X 1, X 2,…, X n X_1, X_2, …, X_nX1X2Xn, Among them X i X_iXiTake 0 or 1, which means the ith item is selected or not), V i V_iViRepresents the value of the ith item, W i W_iWiIndicates the volume (weight) of the i-th item;
  2. Establish a model and find max (V 1 X 1 + V 2 X 2 +… + V n X n) max(V_1X_1+V_2X_2+…+V_nX_n)m and x ( V1X1+V2X2++VnXn)
  3. 约束条件, W 1 X 1 + W 2 X 2 + … + W n X n < c a p a c i t y W_1X_1+W_2X_2+…+W_nX_n<capacity W1X1+W2X2++WnXn<capacity
  4. Definition V(i,j): the current backpack capacity j, the value corresponding to the best combination of the first i items;
  5. The principle of optimality is the basis of dynamic programming. The principle of optimality refers to "the optimal decision sequence of a multi-stage decision-making process has such a property: Regardless of the initial state and initial decision, for a certain state caused by the previous decision , The decision sequence of each subsequent stage must constitute the optimal strategy."
  6. Looking for a recurrence relationship, there are two possibilities for the current commodity:
  • First, the capacity of the bag is smaller than the volume of the product and cannot fit. The value at this time is the same as the value of the previous i-1, that is, V(i,j)=V(i-1,j);
  • Second, there is enough capacity to install the product, but it may not reach the current optimal value after it is installed, so choose the best one between installed and not installed, that is, V(i,j)=max{V (i-1,j), V(i-1,jw(i))+v(i)}
  • Among them, V(i-1,j) means not to install, V(i-1,jw(i))+v(i) means to install the i-th product, the backpack capacity decreases by w(i) but the value increases by v( i);
  • From this, the recurrence relation can be derived:
  • 1) j<w(i) V(i,j)=V(i-1,j)
  • 2) j>=w(i) V(i,j)=max{ V(i-1,j),V(i-1,j-w(i))+v(i) }
  1. Fill in the form
    First initialize the boundary conditions, V(0,j)=V(i,0)=0;
    Insert picture description here
    then fill in the form line by line,
  • 如,i=1,j=1,w(1)=2,v(1)=3,有j<w(1),故V(1,1)=V(1-1,1)=0;
  • For example, i=1, j=2, w(1)=2, v(1)=3, and j=w(1), so V(1,2)=max{V(1-1,2), V(1-1,2-w(1))+v(1) }=max{0, 0+3}=3;
  • Continue like this, fill in the last one, i=4, j=8, w(4)=5, v(4)=6, there is j>w(4), so V(4,8)=max{V( 4-1,8),V(4-1,8-w(4))+v(4) }=max{9,4+6}=10;
  • So fill out the form as shown below:
    Insert picture description here
  1. Code
void Bag()
{
    
    
    int i,j;
    //填表
    for(i=1;i<=number;i++)
    {
    
    
        for(j=1;j<=capacity;j++)
        {
    
    
            if(j<w[i])//装不进包
            {
    
    
                V[i][j]=V[i-1][j];
            }
            else//能装进去
            {
    
    
                if(V[i-1][j]>V[i-1][j-w[i]]+v[i])//不装价值大
                {
    
    
                    V[i][j]=V[i-1][j];
                }
                else//前i-1个物品的最优解与第i个物品的价值之和更大
                {
    
    
                    V[i][j]=V[i-1][j-w[i]]+v[i];
                }
            }
        }
    }
}
  1. Backtracking to find out the composition of the solution based on the optimal solution
    Insert picture description here
void FindAns(int i,int j)//寻找解的组成方式
{
    
    
    if(i>=0)
    {
    
    
        if(V[i][j]==V[i-1][j])//相等说明没装
        {
    
    
            item[i]=0;//全局变量,标记未被选中
            FindAns(i-1,j);
        }
        else if( j-w[i]>=0 && V[i][j]==V[i-1][j-w[i]]+v[i] )
        {
    
    
            item[i]=1;//标记已被选中
            FindAns(i-1,j-w[i]);//回到装包之前的位置
        }
    }
}

Space optimization

Space optimization, the value of each change of V(i)(j) is only related to V(i-1)(x) {x:1...j}, V(i-1)(x) is saved in the previous i cycle down value;
Accordingly, the V reduced to a one-dimensional array, so as to achieve the purpose of optimizing space, state transition equation is converted to B (j) = max {B (j), B (jw (i)) + v (i) };
And, the state transition equation, each time V(i)(j) is derived through V(i-1)(jw(i)), so the scanning order of j in the one-dimensional array should be from large to small (capacity to 0), otherwise the value saved in the previous cycle will be modified, causing an error.
When i=3, the following figure is used to calculate
Insert picture description here
if j is not in reverse order but positive order j=0...capacity, as shown in the figure above, when j=8, there should be B(8)=B(8-w(3)) +v(3)=B(4)+5, but at this time B(4) has been modified when j=4, the original B(4)=4, now B(4)=5, So the calculation shows that B(8)=5+5=10, which obviously does not match the correct answer; therefore, the value behind the one-dimensional array needs to be calculated and then changed by the previous value. If the positive order is convenient, the previous value will be It may be modified to cause errors in the subsequent data; on the contrary, if you traverse in reverse order, modify the subsequent data first and then modify the previous data, there will be no errors in this case;

void BagBetter()//优化空间后的动态规划
{
    
    
    int i,j;
    for(i=1;i<=number;i++)
    {
    
    
        for(j=capacity;j>=0;j--)
        {
    
    
            if(B[j]<=B[j-w[i]]+v[i] && j-w[i]>=0 )//二维变一维
            {
    
    
                B[j]=B[j-w[i]]+v[i];
            }
        }
    }
}

However, the disadvantage is that although the space of dynamic programming is optimized, this method cannot find the solution composition of the optimal solution, because dynamic programming must search for the early solution composition on the premise that the optimal solution is determined. , And the optimized dynamic programming only uses a one-dimensional array, and the previous data has been overwritten, so there is no way to find it, so the two methods have their own advantages.

summary

The original problem to be solved by dynamic programming is more difficult, but this problem can be continuously broken down into small problems, and the solution of small problems is very easy to obtain; if you only use recursive methods to solve the original problem, then use It is the idea of ​​divide and conquer. Dynamic programming is memorable and records the solutions of sub-problems to avoid repeated calculations in the recursive process, thereby reducing the amount of calculations.

Guess you like

Origin blog.csdn.net/qq_32505207/article/details/107945479