Top ten algorithms commonly used by programmers (3): Dynamic programming algorithm (filling table method) to solve 01 knapsack problem

Dynamic programming algorithm (form filling method)

Basic introduction:
1) The core idea of ​​the dynamic programming algorithm is to divide the big problem into small problems to solve, so as to obtain the optimal solution step by step.
2) The dynamic programming algorithm is similar to the divide-and-conquer algorithm. Its basic idea is to decompose the problem to be solved into several sub-problems, first solve the sub-problems, and then obtain the solution of the original problem from the solutions of these sub-problems.
3) Different from the divide-and-conquer method Yes, it is suitable for problems solved by dynamic programming algorithms, and the sub-problems obtained by decomposition are often not independent of each other . (That is, the solution of the next sub-stage is based on the solution of the previous sub-stage, and further solutions are performed.)
4) The dynamic programming algorithm can be gradually advanced by filling in the table to obtain the optimal solution.

Case introduction:

Backpack problem:
There is a backpack that can hold 4 kg of things. There are the following items:
Insert picture description here
1. The required goal is to maximize the total value of the backpack and the weight does not exceed the capacity of the backpack
. 2. The required items are not repeated
(in addition One case is an infinite backpack: that is, each item has unlimited pieces to put. Let’s use a non-repeatable backpack as an example here)

Analysis of thinking:
Solving similar problems can be broken down into small problems to be solved. Assuming that there are backpacks with various capacities of 1, 2, 3, 4 (the rules for distributing capacity are integer multiples of the minimum weight) )
As shown in the figure: The
Insert picture description here
first row of items is empty, which means that no items are loaded into the backpack. At this time, no matter how large the backpack is, the total value is 0. The
second column is empty, which means the capacity of the backpack is empty.
Step 1 :
If there is only a mobile phone, at this time, no matter how large the backpack is, you can only put a guitar (cannot be repeated).
Insert picture description here
Step 2:
If you have a mobile phone and a laptop, when the backpack capacity is only 1 kg, you can only put a mobile phone:
Insert picture description here
as a backpack
Insert picture description here
When the capacity is two kilograms and three kilograms , it still can’t fit the notebook; when the backpack has four kilograms capacity, you can put a mobile phone or a notebook, and find that C (notebook)>C (mobile phone) (C means value)
so:

third Step:
Three kinds are complete:

Idea analysis:

  • i represents a row in the table
  • j represents a column in the table
  • w[i]: the weight of the i-th item
  • v[i]: the value of the i-th item
  • v[i][j]: Represents the maximum value that can be loaded into the backpack with capacity j in the first i items.
    For the i-th item that is traversed each time, determine whether the item needs to be put into the backpack according to w[i] and v[i]. So:
    1) v[i][0]=v[0][j]=0 ;
    (when the backpack capacity is 0 or the item value is 0, the maximum value is 0)
    2) when w[i]>j When: v[i][j]=v[i-1][j]
    (When the weight of the i-th item is greater than the capacity of the backpack, the loading strategy of i-1 (ie the previous) item is used directly
    3) When j>=w[i]: v[i][j]=max{v[i-1][j],v[i-1][jw[i]]+v[i]}
    (when The capacity of the new product to be loaded is less than the capacity of the current backpack.
    The method of loading is:
    v[i-1][j]: the maximum value when the previous item is loaded
    jw[i-1] is loaded After i, the remaining space of the computer and the value of the remaining space that can be installed plus the value
    that has been added are compared with the previous value (that is, the value of v[i-1][j]) to see which is greater.

If you don’t understand the above formula, please see the following example:
First, let’s take the figure in the third step as an example.
If there are mobile phones and laptops, the
verification formula:
v[1][1]=1500 (that is, the capacity of 1 kg) The value of a mobile phone in a backpack)
1) When i=1, j=1
2)w[i]=w[1]=1
w[1]=1 j=1 Include the formula:
v[i][j ] = max {v [i- 1] [j], v [i] + v [i-1] -w [i]}:
to give
v [1] [1] = max {v [0] [1] ,v[1]+v[0][1-1]}=max{0,1500}

Verification formula:
v[3][4]
1)i=3;j=4
w[i]=w[3]=3;j=4
j=4 is greater than w[i]=3
v[3][4 ]=max{v[2][4],v[3]+v[2][1]}=max{3000,2000+1500}=3500

Code

package dynamic;

public class KnapsackProblem {
    
    
	public static void main(String[] args) {
    
    
		int[] w= {
    
    1,4,3};//物品重量
		int[] val= {
    
    1500,3000,2000};//物品价值
		int m=4;//背包容量
		int n=val.length;//物品个数
		
		//创建二维数组,表
		//v[i][j]:表示在前i个物品中能够装入容量为j的背包中的最大价值。
		int[][] v=new int[n+1][m+1];

		
		//初始化第一行和第一列
		for(int i=0;i<v.length;i++) {
    
    
			v[i][0]=0;//讲第一列设置为0
		}
		for(int i=0;i<v[0].length;i++) {
    
    
			v[0][i]=0;//将第一行设置为0
		}
		
		//根据前面得到得公式来动态规划处理
		for(int i=1;i<v.length;i++) {
    
    //从1开始,不处理第一行
			for(int j=1;j<v[0].length;j++) {
    
    //不处理第一列
				//套用公式:(i从1开始,公式中得w[i]和val[i]中的i需减一
				if(w[i-1]>j) {
    
    
					v[i][j]=v[i-1][j];
				}else {
    
    
					v[i][j]=Math.max(v[i-1][j], val[i-1]+v[i-1][j-w[i-1]]);
				}
			}
		}
		//打印表:
		for(int i=0;i<v.length;i++) {
    
    
			for(int j=0;j<v[i].length;j++) {
    
    
				System.out.print(v[i][j]+" ");
			}
			System.out.println();
		}
		
	}
}

Guess you like

Origin blog.csdn.net/qq_45273552/article/details/109315031